আমি সিটিতে আমার অ্যারের আকারটি কীভাবে নির্ধারণ করব?


1028

আমি সিটিতে আমার অ্যারের আকারটি কীভাবে নির্ধারণ করব?

অর্থাৎ অ্যারে কতগুলি উপাদান ধারণ করতে পারে?


2
প্রকারের সুরক্ষার জন্য দেখুন স্ট্যাকওভারফ্লো
টিএস

3
অভিনন্দন 1000 upvotes পৌঁছেছেন!
এসএস আন

উত্তর:


1258

নির্বাহী সারসংক্ষেপ:

int a[17];
size_t n = sizeof(a)/sizeof(a[0]);

পুরো উত্তর:

বাইটে আপনার অ্যারের আকার নির্ধারণ করতে, আপনি sizeof অপারেটরটি ব্যবহার করতে পারেন :

int a[17];
size_t n = sizeof(a);

আমার কম্পিউটারে ইনসটি 4 বাইট দীর্ঘ, সুতরাং এন 68।

অ্যারেতে উপাদানগুলির সংখ্যা নির্ধারণ করতে, আমরা অ্যারের উপাদানটির আকার দ্বারা অ্যারের মোট আকার বিভাজন করতে পারি। আপনি এই জাতীয় ধরণের সাহায্যে এটি করতে পারেন:

int a[17];
size_t n = sizeof(a) / sizeof(int);

এবং সঠিক উত্তরটি পান (68/4 = 17), তবে aপরিবর্তনের ধরণটি যদি আপনিও পরিবর্তন করতে ভুলে যান তবে আপনার একটি বাজে বাগ লাগবে sizeof(int)

সুতরাং পছন্দসই বিভাজক sizeof(a[0])বা সমমান sizeof(*a), অ্যারের প্রথম উপাদানটির আকার।

int a[17];
size_t n = sizeof(a) / sizeof(a[0]);

আর একটি সুবিধা হ'ল আপনি এখন ম্যাক্রোতে সহজেই অ্যারের নামটি প্যারামিটারাইজ করতে পারবেন এবং পাবেন:

#define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))

int a[17];
size_t n = NELEMS(a);

6
উত্পন্ন কোডটি অভিন্ন হবে, যেহেতু সংকলক সংকলনের সময় * int_arr এর প্রকারটি জানে (এবং সেইজন্য আকারের (* int_arr)) এর মান। এটি একটি ধ্রুবক হবে এবং সংকলক সেই অনুযায়ী অনুকূল করতে পারে।
মার্ক হ্যারিসন

10
সমস্ত সংকলকগুলির ক্ষেত্রে এটি হওয়া উচিত, যেহেতু আকারের ফলাফলগুলি সংকলন-সময় ধ্রুবক হিসাবে সংজ্ঞায়িত হয়।
মার্ক হ্যারিসন

449
গুরুত্বপূর্ণ : এখানে পড়া বন্ধ করবেন না, পরবর্তী উত্তরটি পড়ুন! এটি কেবল স্ট্যাকের অ্যারেগুলির জন্যই কাজ করে , যেমন আপনি যদি মেলোক () ব্যবহার করছেন বা কোনও ফাংশন প্যারামিটার অ্যাক্সেস করছেন তবে আপনার ভাগ্য খুব খারাপ। নিচে দেখ.
মারকাস

7
সি বা সি ++ তে উইন্ডোজ এপিআই প্রোগ্রামিংয়ের জন্য ARRAYSIZEম্যাক্রো সংজ্ঞায়িত করা আছে WinNT.h(যা অন্য শিরোলেখ দ্বারা টানা হয়)। সুতরাং WinAPI ব্যবহারকারীদের তাদের নিজস্ব ম্যাক্রো সংজ্ঞায়িত করার দরকার নেই।
লুমি

17
@ মারকাস এটি যে কোনও ভেরিয়েবলের জন্য কাজ করে যার অ্যারে টাইপ রয়েছে; এটি "স্ট্যাকের" হতে হবে না। যেমন static int a[20];। তবে আপনার মন্তব্য পাঠকদের পক্ষে দরকারী যা কোনও অ্যারে এবং পয়েন্টারের মধ্যে পার্থক্য বুঝতে পারে না।
এমএম

807

sizeofপথ সঠিক উপায় iff আপনি প্যারামিটার হিসেবে পাইনি অ্যারে সঙ্গে তার আচরণ করছে। কোনও ফাংশনে প্যারামিটার হিসাবে প্রেরিত অ্যারেটিকে পয়েন্টার হিসাবে বিবেচনা করা হয়, সুতরাং sizeofঅ্যারের পরিবর্তে পয়েন্টারের আকারটি ফিরে আসবে।

সুতরাং, ভিতরে ফাংশনগুলি এই পদ্ধতিটি কাজ করে না। পরিবর্তে, size_t sizeঅ্যারেতে উপাদানগুলির সংখ্যা নির্দেশ করে অতিরিক্ত প্যারামিটারটি সর্বদা পাস করুন ।

টেস্ট:

#include <stdio.h>
#include <stdlib.h>

void printSizeOf(int intArray[]);
void printLength(int intArray[]);

int main(int argc, char* argv[])
{
    int array[] = { 0, 1, 2, 3, 4, 5, 6 };

    printf("sizeof of array: %d\n", (int) sizeof(array));
    printSizeOf(array);

    printf("Length of array: %d\n", (int)( sizeof(array) / sizeof(array[0]) ));
    printLength(array);
}

void printSizeOf(int intArray[])
{
    printf("sizeof of parameter: %d\n", (int) sizeof(intArray));
}

void printLength(int intArray[])
{
    printf("Length of parameter: %d\n", (int)( sizeof(intArray) / sizeof(intArray[0]) ));
}

আউটপুট (64৪-বিট লিনাক্স ওএসে):

sizeof of array: 28
sizeof of parameter: 8
Length of array: 7
Length of parameter: 2

আউটপুট (32-বিট উইন্ডোজ ওএসে):

sizeof of array: 28
sizeof of parameter: 4
Length of array: 7
Length of parameter: 1

10
কেন length of parameter:2যদি ১ ম অ্যারে এলিমেন্টের কেবলমাত্র একটি পয়েন্টার পাস হয়?
বিবিভারেহে

16
@ বিবার্ভারে এর কারণ 64৪ বিট সিস্টেমে পয়েন্টারগুলি 8 বাইট (মাপের (ইনট্রাই)) হয় তবে ইনটগুলি এখনও (সাধারণত) 4 বাইট দীর্ঘ (আকারের (ইনআটারে [0])) থাকে।
এলিদেব

13
@ পেসারিয়র: কোনও সঠিক কোড নেই - সাধারণ সমাধান হ'ল অ্যারের সাথে দৈর্ঘ্য পৃথক যুক্তি হিসাবে পাস করা।
জিন হোমিনাল

10
অপেক্ষা করুন, সুতরাং পয়েন্টার থেকে সরাসরি অ্যারে অ্যাক্সেস করার এবং এর আকার দেখার কোনও উপায় নেই? সি এখানে নতুন।
sudo

7
@Michael Trouw যদি তোলে আপনি ভাল বোধ হয় অপারেটর সিনট্যাক্স ব্যবহার করতে পারেন: (sizeof array / sizeof *array)
chqrlie

134

এটি sizeofএকটি পয়েন্টারের কাছে ক্ষয় হয়ে যাওয়া অ্যারের মানের সাথে কাজ করার সময় সাহায্য করে না: এটি অ্যারের শুরুতে নির্দেশ করে, সংকলকটিতে এটি যে অ্যারের একক উপাদানের পয়েন্টার হিসাবে একই । পয়েন্টার অ্যারে যা আরম্ভ করার জন্য ব্যবহৃত হয়েছিল সে সম্পর্কে অন্য কিছু মনে রাখে না।

int a[10];
int* p = a;

assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));

1
@ ম্যাগনাস: স্ট্যান্ডার্ডটি আকারের আকারটিকে সংজ্ঞা দেয় যেহেতু বস্তুটিতে বাইট সংখ্যা পাওয়া যায় এবং সেই আকারের (চর) সর্বদা এক। বাইটে বিটের সংখ্যা বাস্তবায়ন নির্দিষ্ট। সম্পাদনা করুন: এএনএসআই সি ++ স্ট্যান্ডার্ড বিভাগ 5.3.3 মাপ: "মাপের অপারেটর তার অপারেন্ডের অবজেক্টের উপস্থাপনায় বাইটের সংখ্যা দেয় [ 1; অন্য যে কোনও মৌলিক ধরণের ক্ষেত্রে প্রয়োগের আকারের প্রয়োগটি বাস্তবায়ন-সংজ্ঞায়িত ""
স্কিজ

বিভাগ 1.6 সি ++ মেমরি মডেল: "সি ++ মেমরি মডেলের মূল স্টোরেজ ইউনিটটি বাইট A যার বাস্তবায়ন সংজ্ঞায়িত। "
স্কিজ

2
আমার মনে আছে সিআরএতে char32 টি বিট সহ সি ছিল । সমস্ত মান বলে যে 0 থেকে 127 পর্যন্ত পূর্ণসংখ্যার মানগুলি উপস্থাপিত হতে পারে এবং এর পরিসীমা কমপক্ষে -127 থেকে 127 (চর স্বাক্ষরিত) বা 0 থেকে 255 (চর স্বাক্ষরযুক্ত নয়) either
ভনব্র্যান্ড

5
এটি একটি দুর্দান্ত প্রতিক্রিয়া। আমি মন্তব্য করতে চাই যে উপরের সমস্ত দাবিগুলি সত্যে মূল্যায়ন করা হয়।
জাভাদ

49

"ট্রিক" আকারটি আমি জানি সবচেয়ে ভাল উপায়, একটি ছোট কিন্তু (আমার কাছে এটি একটি বড় পোষা প্রাইভ হিসাবে) প্রথম বন্ধনী ব্যবহারের ক্ষেত্রে গুরুত্বপূর্ণ পরিবর্তন।

উইকিপিডিয়া এন্ট্রি যেমন পরিষ্কার করে দেয়, সি এর sizeofকোনও কাজ নয়; এটি একটি অপারেটর । সুতরাং, যুক্তির প্রকারের নাম না হলে এটির পক্ষে তার যুক্তির চারপাশে প্রথম বন্ধনী প্রয়োজন হয় না। এটি মনে রাখা সহজ, যেহেতু এটি যুক্তিটিকে castালাইয়ের মত প্রকাশের মতো করে তোলে, যা বন্ধনী ব্যবহার করে।

সুতরাং: আপনার যদি নিম্নলিখিত থাকে:

int myArray[10];

আপনি এই জাতীয় কোড সহ উপাদানের সংখ্যা খুঁজে পেতে পারেন:

size_t n = sizeof myArray / sizeof *myArray;

এটি আমার কাছে প্রথম বন্ধনের বিকল্পের চেয়ে অনেক সহজ পড়ছে reads আমি বিভাগের ডান হাতের অংশেও নক্ষত্রের ব্যবহারের পক্ষে, কারণ এটি সূচকের চেয়ে সংক্ষিপ্ততর।

অবশ্যই, এটিও সমস্ত সংকলন-সময়, সুতরাং প্রোগ্রামটির কর্মক্ষমতা প্রভাবিত করে এমন বিভাগ সম্পর্কে চিন্তা করার দরকার নেই। সুতরাং আপনি যেখানেই পারেন এই ফর্মটি ব্যবহার করুন।

কোনও ধরণের পরিবর্তে যখন আপনার একটি থাকে তখন কোনও আসল অবজেক্টে মাপের ব্যবহার করা সর্বদা সেরা since তারপরে আপনাকে ত্রুটি তৈরি করার এবং ভুল ধরণের উল্লেখ করার বিষয়ে চিন্তা করার দরকার নেই।

উদাহরণস্বরূপ, বলুন আপনার একটি ফাংশন রয়েছে যা কোনও নেটওয়ার্ক জুড়ে উদাহরণস্বরূপ কিছু বাইটস স্ট্রিম হিসাবে ডেটা দেয়। আসুন ফাংশনটি কল করি send()এবং এটি আর্গুমেন্ট হিসাবে পাঠানোর জন্য কোনও পয়েন্টার এবং অবজেক্টে বাইটের সংখ্যা হিসাবে গ্রহণ করি। সুতরাং, প্রোটোটাইপ হয়ে যায়:

void send(const void *object, size_t size);

এবং তারপরে আপনাকে একটি পূর্ণসংখ্যার প্রেরণ করতে হবে, সুতরাং আপনি এটিকে এভাবে কোড করুন:

int foo = 4711;
send(&foo, sizeof (int));

এখন, আপনি নিজের জায়গায় শুটিংয়ের একটি সূক্ষ্ম উপায় চালু করেছেন, fooদুটি জায়গার প্রকার উল্লেখ করে । যদি একটি পরিবর্তন হয় তবে অন্যটি পরিবর্তন না করে তবে কোডটি ব্রেক হয়ে যায়। সুতরাং, সর্বদা এটির মতো করুন:

send(&foo, sizeof foo);

এখন আপনি সুরক্ষিত অবশ্যই, আপনি ভেরিয়েবলটির নামটি নকল করে ফেলেন, তবে এটি পরিবর্তন করে যদি সংকলক সনাক্ত করতে পারে এমনভাবে এটি ভাঙ্গার উচ্চ সম্ভাবনা রয়েছে।


বিটিডব্লিউ, তারা কি প্রসেসরের পর্যায়ে অভিন্ন নির্দেশনা রয়েছে? এর sizeof(int)চেয়ে কম নির্দেশের দরকার কি sizeof(foo)?
পেসারিয়ার

@ পেসারিয়র: না, তারা অভিন্ন। int x = 1+1;বনাম ভাবুন int x = (1+1);। এখানে, বন্ধনীগুলি সম্পূর্ণ নিখুঁতভাবে নান্দনিক।
কোয়েটজলকোটল

@ এডিয়াকাপি এটি সত্য নয়, সি 99 ভিএলএস বিবেচনা করুন।
13-18

@ আনউইন্ড ধন্যবাদ, আমি সংশোধন করছি। আমার মন্তব্য সংশোধন করতে, sizeofসর্বদা সি ++ এবং সি 89 এ ধ্রুব থাকবে। C99 এর পরিবর্তনশীল দৈর্ঘ্যের অ্যারে সহ, এটি রানটাইম সময়ে মূল্যায়ন করা যেতে পারে।
এইডিয়াকাপি

2
sizeofঅপারেটর হতে পারে তবে লিনাস টরভাল্ডস অনুসারে এটি একটি ফাংশন হিসাবে বিবেচিত হওয়া উচিত। আমি রাজী. তার যৌক্তিকতা এখানে পড়ুন: lkML.org/lkML/2012/7/11/103
ডাঃ ব্যক্তি দ্বিতীয় ব্যক্তি

37
int size = (&arr)[1] - arr;

ব্যাখ্যার জন্য এই লিঙ্কটি দেখুন


7
ছোট নিটপিক: পয়েন্টার বিয়োগের ফলাফলের ধরন রয়েছে ptrdiff_t। (সাধারণত 64৪-বিট সিস্টেমে এটির চেয়ে বড় ধরণের হবে int)। এমনকি যদি আপনি পরিবর্তন intকরতে ptrdiff_tএই কোডে, এটা এখনও একটি বাগ যদি গেছে arrঅ্যাড্রেস স্পেস অর্ধেকের বেশি লাগে।
এমএম

2
@ এমএম আরেকটি ছোট্ট নিটপিক: আপনার সিস্টেমের আর্কিটেকচারের উপর নির্ভর করে, বেশিরভাগ সিস্টেমে অ্যাড্রেস স্পেস পয়েন্টার আকারের চেয়ে প্রায় বড় নয়। উদাহরণস্বরূপ উইন্ডোজ 64৪-বিট অ্যাপ্লিকেশনগুলির জন্য ঠিকানা স্থানটিকে 8 টিবি বা 44 বিটের মধ্যে সীমাবদ্ধ করে। সুতরাং উদাহরণস্বরূপ আপনার ঠিকানার জায়গার অর্ধেকের চেয়ে বড় অ্যারে থাকলেও এটি কোনও বাগ হবে না। কেবলমাত্র যদি আপনার ঠিকানার স্থানগুলি systems সিস্টেমে 63৩-বিট অতিক্রম করে তবে এমন বাগের মুখোমুখি হওয়াও সম্ভব। সাধারণভাবে, এটি সম্পর্কে চিন্তা করবেন না।
এইডিয়াকাপি

1
@ এডিয়াকাপি 32-বিট x86 লিনাক্সে বা উইন্ডোজে /3Gবিকল্পের সাথে আপনার 3 জি / 1 জি ব্যবহারকারী / কার্নেল বিভাজন রয়েছে, যা আপনাকে ঠিকানা স্থানের আকারের 75% পর্যন্ত অ্যারে আকার দিতে দেয়।
Ruslan

1
foo buf1[80]; foo buf2[sizeof buf1/sizeof buf1[0]]; foo buf3[(&buf1)[1] - buf1];গ্লোবাল ভেরিয়েবল হিসাবে বিবেচনা করুন । buf3[]ঘোষণা যেমন (&buf1)[1] - buf1একটি ধ্রুবক নয় ত্রুটিযুক্ত ।
chux - মনিকা পুনরায় ইনস্টল করুন

2
এটি প্রযুক্তিগতভাবে অপরিজ্ঞাত আচরণ হিসাবে মানটি স্পষ্টভাবে একটি অ্যারের শেষের আগে ডিফারেন্সিংকে অস্বীকার করে (আপনি সঞ্চিত মূল্য পড়ার চেষ্টা না করলেও)
এমএম

26

আপনি আকারের অপারেটরটি ব্যবহার করতে পারেন তবে এটি ফাংশনগুলির জন্য কাজ করবে না কারণ এটি বিন্যাসের রেফারেন্স নেবে আপনি কোনও অ্যারের দৈর্ঘ্য সন্ধান করতে নিম্নলিখিতটি করতে পারেন:

len = sizeof(arr)/sizeof(arr[0])

কোডটি মূলত এখানে পাওয়া গেছে: একটি অ্যারেতে উপাদানের সংখ্যা খুঁজতে সি প্রোগ্রাম


21

আপনি যদি অ্যারের ডাটা টাইপটি জানেন তবে আপনি এমন কিছু ব্যবহার করতে পারেন:

int arr[] = {23, 12, 423, 43, 21, 43, 65, 76, 22};

int noofele = sizeof(arr)/sizeof(int);

অথবা যদি আপনি অ্যারের ডেটা ধরণ জানেন না তবে আপনি এর মতো কিছু ব্যবহার করতে পারেন:

noofele = sizeof(arr)/sizeof(arr[0]);

দ্রষ্টব্য: এই জিনিসটি কেবল তখনই কাজ করে যদি রান সময়টিতে অ্যারে সংজ্ঞায়িত না করা হয় (যেমন malloc) এবং অ্যারে কোনও ফাংশনে পাস করা হয় না। উভয় ক্ষেত্রে arr(অ্যারের নাম) একটি পয়েন্টার।


4
int noofele = sizeof(arr)/sizeof(int);কোডিংয়ের চেয়ে আধ-রাস্তা ভাল int noofele = 9;। ব্যবহার করে sizeof(arr)নমনীয়তা বজায় রাখে অ্যারের আকার পরিবর্তন হওয়া উচিত। তবুও পরিবর্তনের sizeof(int)ধরণের উচিত একটি আপডেট দরকার arr[]sizeof(arr)/sizeof(arr[0])প্রকারটি ভাল জানা থাকলেও ব্যবহার করা ভাল। কেন ব্যবহার অস্পষ্ট intজন্য noofeleবনাম size_tটাইপ দ্বারা ফিরে sizeof()
chux - মনিকা

19

ARRAYELEMENTCOUNT(x)সকলেই যে ম্যাক্রোটি ভুলভাবে মূল্যায়ন ব্যবহার করছে । বাস্তবে এটি কেবল একটি সংবেদনশীল বিষয়, কারণ আপনার এমন অভিব্যক্তি থাকতে পারে না যার ফলস্বরূপ 'অ্যারে' টাইপ হয়।

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x[0]))

ARRAYELEMENTCOUNT(p + 1);

আসলে হিসাবে মূল্যায়ন:

(sizeof (p + 1) / sizeof (p + 1[0]));

যেহেতু

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x)[0])

ARRAYELEMENTCOUNT(p + 1);

এটি সঠিকভাবে মূল্যায়ন করে:

(sizeof (p + 1) / sizeof (p + 1)[0]);

স্পষ্টভাবে অ্যারের আকারের সাথে এটির খুব বেশি কিছু করার নেই। সি প্রিপ্রোসেসর কীভাবে কাজ করে তা সত্যই পর্যবেক্ষণ না করে আমি অনেকগুলি ত্রুটি লক্ষ্য করেছি। আপনি সর্বদা ম্যাক্রো প্যারামিটারটি মোড়েন, এতে কোনও অভিব্যক্তি জড়িত থাকতে পারে না।


এটি সঠিক; আমার উদাহরণটি খারাপ ছিল। তবে বাস্তবে যা হওয়া উচিত তা হ'ল। আমি পূর্বে উল্লিখিত p + 1হিসাবে একটি পয়েন্টার টাইপ হিসাবে শেষ হবে এবং পুরো ম্যাক্রো অকার্যকর (ঠিক যেমন আপনি একটি পয়েন্টার প্যারামিটার সহ একটি ফাংশনে ম্যাক্রো ব্যবহার করার চেষ্টা করেছেন)।

দিনের শেষে, এই বিশেষ উদাহরণে, দোষটি আসলেই কিছু যায় আসে না (তাই আমি কেবল প্রত্যেকের সময় নষ্ট করছি; হুজ্জা!), কারণ আপনার এক ধরণের 'অ্যারে' দিয়ে অভিব্যক্তি নেই। তবে প্রকৃতপক্ষে প্রিপ্রোসেসর মূল্যায়ন সাবটেলগুলি সম্পর্কে আমি মনে করি এটি একটি গুরুত্বপূর্ণ।


2
ব্যাখ্যার জন্য ধন্যবাদ. মূল সংস্করণটি একটি সংকলন-সময় ত্রুটির ফলাফল দেয়। ঝাঁকুনির প্রতিবেদন "সাবস্ক্রিপ্ট করা মান কোনও অ্যারে, পয়েন্টার বা ভেক্টর নয়"। এই উদাহরণে এটি পছন্দনীয় আচরণ বলে মনে হচ্ছে, যদিও ম্যাক্রোগুলিতে মূল্যায়ন আদেশ সম্পর্কে আপনার মতামত ভালভাবে নেওয়া হয়েছে।
মার্ক হ্যারিসন

1
কোনও ভুল ধরণের স্বয়ংক্রিয় বিজ্ঞপ্তি হিসাবে আমি সংকলক অভিযোগ সম্পর্কে ভাবি নি। ধন্যবাদ!

3
ব্যবহার না করার কোনও কারণ আছে (sizeof (x) / sizeof (*x))?
গুরুতরদেব

16

জন্য বহুমাত্রিক অ্যারে এটা একটি বাচ্চা জটিল। প্রায়শই লোকেরা সুস্পষ্ট ম্যাক্রো কনস্ট্যান্টগুলি সংজ্ঞায়িত করে, যেমন

#define g_rgDialogRows   2
#define g_rgDialogCols   7

static char const* g_rgDialog[g_rgDialogRows][g_rgDialogCols] =
{
    { " ",  " ",    " ",    " 494", " 210", " Generic Sample Dialog", " " },
    { " 1", " 330", " 174", " 88",  " ",    " OK",        " " },
};

তবে এই ধ্রুবকগুলি আকারের সাথে কমপাইল সময়েও মূল্যায়ন করা যায় :

#define rows_of_array(name)       \
    (sizeof(name   ) / sizeof(name[0][0]) / columns_of_array(name))
#define columns_of_array(name)    \
    (sizeof(name[0]) / sizeof(name[0][0]))

static char* g_rgDialog[][7] = { /* ... */ };

assert(   rows_of_array(g_rgDialog) == 2);
assert(columns_of_array(g_rgDialog) == 7);

মনে রাখবেন যে এই কোডটি সি এবং সি ++ এ কাজ করে। দুটি মাত্রার বেশি ব্যবহার সহ অ্যারেগুলির জন্য

sizeof(name[0][0][0])
sizeof(name[0][0][0][0])

ইত্যাদি।


15
sizeof(array) / sizeof(array[0])

টাইপটির উপর নির্ভরশীল array, আপনি উভয়ের একটি অ্যারে sizeof(array) / sizeof(array[0])হলে ব্যবহার করার প্রয়োজন নেই , বা - C18,6.5.3.4 / 4 থেকে উদ্ধৃতি: "যখন আকারটি কোনও অপরেন্ডে প্রয়োগ করা হয় যেখানে টাইপ চর, স্বাক্ষরবিহীন চর বা স্বাক্ষর করা চর রয়েছে , (বা এর একটি যোগ্য সংস্করণ) ফলাফলটি ১। " এই ক্ষেত্রে আপনি আমার উত্সর্গীকৃত উত্তরে বর্ণিত হিসাবে সহজভাবে করতে পারেন । arraycharunsigned charsigned charsizeof(array)
রবার্টস 13:52

15

সি তে একটি অ্যারের আকার:

int a[10];
size_t size_of_array = sizeof(a);      // Size of array a
int n = sizeof (a) / sizeof (a[0]);    // Number of elements in array a
size_t size_of_element = sizeof(a[0]); // Size of each element in array a                                          
                                       // Size of each element = size of type

4
size_t size_of_elementintint n = sizeof (a) / sizeof (a[0]); size_t n = sizeof (a) / sizeof (a[0]);
কৌতূহলীয়

1
হাই @ যোগেশ এইচটি, আপনি দয়া করে চুকসের সন্দেহের উত্তর দিতে পারেন। আমি জানতে আগ্রহী যে কীভাবে এনটি = আকারের (ক) / সাইজফ (এ [0]) অ্যারের দৈর্ঘ্য দিচ্ছে এবং অ্যারের দৈর্ঘ্যের জন্য আমরা কেন সাইজ_টি ব্যবহার করছি না। কেউ কি এর উত্তর দিতে পারে?
মস্তিষ্ক

1
@ ব্রেন মাপের (ক) অ্যারে উপস্থিত সমস্ত উপাদানের আকার দেয় একটি মাপের (একটি [0]) 1 ম উপাদানগুলির আকার দেয়। ধরুন a = {1,2,3,4,5}; মাপের (ক) = 20 বাইটস (যদি মাপের (ইনট) = 4 বাইটস গুন 5), সাইজফ (এ [0]) = 4 বাইটস, সুতরাং 20/4 = 5 অর্থাৎ উপাদানগুলির মধ্যে নেই
যোগেশ এইচটি

2
@YogeeshHT জন্য খুব বড় অ্যারে মত char a[INT_MAX + 1u];, int nযেমন ব্যবহৃত int n = sizeof (a) / sizeof (a[0]);যথেষ্ট নয় (এটা UB যায়)। ব্যবহার size_t n = sizeof (a) / sizeof (a[0]);করে এই সমস্যা হয় না।
chux - মনিকা পুনরায় ইনস্টল করুন

13

আমি sizeofঅ্যারের দুটি ভিন্ন আকারের যে কোনও একটি উপাদান পেতে বা সংখ্যাতে বা বাইটগুলিতে, যা আমি এখানে দেখিয়েছি এটি শেষ দুটি হিসাবে কখনও ব্যবহার করার জন্য ( কখনও এটি ব্যবহার করা হলেও) ব্যবহার করার পরামর্শ দেব। দুটি আকারের প্রত্যেকটির জন্য, নীচে প্রদর্শিত ম্যাক্রোগুলি এটিকে নিরাপদ করতে ব্যবহার করা যেতে পারে। কোডটি রক্ষণাবেক্ষণকারীদের কাছে কোডের উদ্দেশ্যটি স্পষ্ট করে দেখা এবং প্রথম নজরে (যেভাবে এইভাবে লেখা হয়েছিল তা sizeof(ptr)থেকে পৃথক হওয়া sizeof(arr)), যাতে কোডগুলি পড়ার জন্য বাগগুলি তখন সুস্পষ্ট হয়।


টি এল; ডিআর:

#define ARRAY_SIZE(arr)     (sizeof(arr) / sizeof((arr)[0]) + must_be_array(arr))

#define ARRAY_SSIZE(arr)    ((ptrdiff_t)ARRAY_SIZE(arr))

#define ARRAY_BYTES(arr)    (sizeof((arr)[0]) * ARRAY_SIZE(arr))

must_be_array(arr)(নীচে সংজ্ঞায়িত) -Wsizeof-pointer-divবগি যেমন প্রয়োজন (এপ্রিল / 2020 হিসাবে):

#define is_same_type(a, b)      __builtin_types_compatible_p(typeof(a), typeof(b))
#define is_array(a)             (!is_same_type((a), &(a)[0]))
#define Static_assert_array(a)  _Static_assert(is_array(a), "Not a `[]` !")
#define must_be_array(a)        (                                       \
        0 * (int)sizeof(                                                \
                struct {                                                \
                        Static_assert_array(a);                         \
                        char ISO_C_forbids_a_struct_with_no_members__;  \
                }                                                       \
        )                                                               \
)

এই বিষয়ে গুরুত্বপূর্ণ বাগ রয়েছে: https://lkML.org/lkML/2015/9/3/428

লিনাস যে সমাধানটি সরবরাহ করে তার সাথে আমি একমত নই, যা ফাংশনগুলির পরামিতিগুলির জন্য কখনও অ্যারে স্বরলিপি ব্যবহার না করে।

আমি ডকুমেন্টেশন হিসাবে অ্যারে স্বরলিপি পছন্দ করি যে একটি পয়েন্টার অ্যারে হিসাবে ব্যবহৃত হচ্ছে। তবে এর অর্থ হ'ল একটি বোকা-প্রমাণ সমাধান প্রয়োগ করা দরকার যাতে বাগি কোডটি লেখা অসম্ভব।

একটি অ্যারে থেকে আমাদের তিনটি মাপ রয়েছে যা আমরা জানতে চাই:

  • অ্যারের উপাদানগুলির আকার
  • অ্যারেতে উপাদানের সংখ্যা
  • অ্যারে মেমরিতে ব্যবহার করে এমন বাইটের আকার

অ্যারের উপাদানগুলির আকার

প্রথমটি খুব সহজ, এবং আমরা কোনও অ্যারে বা পয়েন্টার নিয়ে কাজ করছি কিনা তা বিবেচ্য নয়, কারণ এটি একইভাবে সম্পন্ন হয়েছে।

ব্যবহারের উদাহরণ:

void foo(ptrdiff_t nmemb, int arr[static nmemb])
{
        qsort(arr, nmemb, sizeof(arr[0]), cmp);
}

qsort() এটির তৃতীয় আর্গুমেন্ট হিসাবে এই মানটির প্রয়োজন।


অন্য দুটি আকারের জন্য, যা প্রশ্নের বিষয়, আমরা তা নিশ্চিত করতে চাই যে আমরা একটি অ্যারের সাথে কাজ করছি, এবং না থাকলে সংকলনটি ভেঙে দেব, কারণ যদি আমরা কোনও পয়েন্টারের সাথে কাজ করে থাকি তবে আমরা ভুল মানগুলি পেয়ে যাব । সংকলনটি নষ্ট হয়ে গেলে, আমরা সহজেই দেখতে পাব যে আমরা কোনও অ্যারের সাথে নয়, পরিবর্তে একটি পয়েন্টারের সাথে ব্যবহার করছি, এবং কেবল মাত্র একটি ভেরিয়েবল বা ম্যাক্রো সহ কোডটি লিখতে হবে যা আকারের আকার সংরক্ষণ করে পয়েন্টারের পিছনে অ্যারে।


অ্যারেতে উপাদানের সংখ্যা

এটি একটি সর্বাধিক সাধারণ এবং অনেক উত্তর আপনাকে সাধারণত ম্যাক্রো ARRAY_SIZE সরবরাহ করেছে:

#define ARRAY_SIZE(arr)     (sizeof(arr) / sizeof((arr)[0]))

প্রদত্ত যে ARRAY_SIZE এর ফলাফল সাধারণত স্বাক্ষরযুক্ত ভেরিয়েবলের ধরণের সাথে ব্যবহৃত হয় ptrdiff_t, এই ম্যাক্রোর স্বাক্ষরিত রূপটি সংজ্ঞায়িত করা ভাল:

#define ARRAY_SSIZE(arr)    ((ptrdiff_t)ARRAY_SIZE(arr))

PTRDIFF_MAXসদস্যদের চেয়ে বেশি সহ অ্যারে ম্যাক্রোর এই স্বাক্ষরিত সংস্করণটির জন্য অবৈধ মান দিতে চলেছে, তবে C17 :: 6.5.6.9 পড়ার মাধ্যমে, এর মতো অ্যারে ইতিমধ্যে আগুনের সাথে খেলছে। শুধুমাত্র ARRAY_SIZEএবং size_tএই ক্ষেত্রে ব্যবহার করা উচিত।

সংস্থাগুলির সাম্প্রতিক সংস্করণগুলি, যেমন জিসিসি 8, আপনি যখন কোনও পয়েন্টারটিতে এই ম্যাক্রো প্রয়োগ করেন তখন আপনাকে সতর্ক করে দেবে, তাই এটি নিরাপদ (পুরানো সংকলকগুলির সাথে এটি নিরাপদ করার অন্যান্য পদ্ধতি রয়েছে)।

এটি প্রতিটি এলিমেন্টের আকারের সাহায্যে পুরো অ্যারের বাইটে আকার ভাগ করে কাজ করে।

ব্যবহারের উদাহরণ:

void foo(ptrdiff_t nmemb)
{
        char buf[nmemb];

        fgets(buf, ARRAY_SIZE(buf), stdin);
}

void bar(ptrdiff_t nmemb)
{
        int arr[nmemb];

        for (ptrdiff_t i = 0; i < ARRAY_SSIZE(arr); i++)
                arr[i] = i;
}

যদি এই ফাংশনগুলি অ্যারে ব্যবহার না করে তবে পরিবর্তে সেগুলি পরামিতি হিসাবে পেয়ে থাকে তবে পূর্ববর্তী কোডটি সংকলন করবে না, তাই বাগটি পাওয়া অসম্ভব (সাম্প্রতিক সংকলক সংস্করণ ব্যবহার করা হয়েছে বা অন্য কোনও কৌশল ব্যবহৃত হয়েছে) , এবং আমাদের মান অনুসারে ম্যাক্রো কলটি প্রতিস্থাপন করতে হবে:

void foo(ptrdiff_t nmemb, char buf[nmemb])
{

        fgets(buf, nmemb, stdin);
}

void bar(ptrdiff_t nmemb, int arr[nmemb])
{

        for (ptrdiff_t i = 0; i < nmemb; i++)
                arr[i] = i;
}

অ্যারে মেমরিতে ব্যবহার করে এমন বাইটের আকার

ARRAY_SIZE পূর্ববর্তী মামলার সমাধান হিসাবে সাধারণত ব্যবহৃত হয়, তবে এই ক্ষেত্রে খুব কমই নিরাপদে লেখা হয়, সম্ভবত এটি কম সাধারণ কারণ।

এই মানটি পাওয়ার সাধারণ উপায়টি হ'ল ব্যবহার করা sizeof(arr)। সমস্যা: আগেরটির মতোই; আপনার যদি অ্যারের পরিবর্তে পয়েন্টার থাকে তবে আপনার প্রোগ্রামটি বাদাম হয়ে যাবে।

সমস্যার সমাধানটিতে আগের মতো একই ম্যাক্রো ব্যবহার করা জড়িত, যা আমরা নিরাপদ থাকতে জানি (এটি কোনও পয়েন্টারের সাথে প্রয়োগ করা হলে এটি সংকলনটি ভেঙে দেয়):

#define ARRAY_BYTES(arr)        (sizeof((arr)[0]) * ARRAY_SIZE(arr))

এটি কীভাবে কাজ করে তা খুব সহজ: এটি বিভাজনকে পূর্বাবস্থায় ফেলে ARRAY_SIZEদেয় যা কাজ করে, তাই গাণিতিক বাতিল হওয়ার পরে আপনি কেবল একটি দিয়ে শেষ করেন sizeof(arr)তবে ARRAY_SIZEনির্মাণের অতিরিক্ত সুরক্ষার সাথে with

ব্যবহারের উদাহরণ:

void foo(ptrdiff_t nmemb)
{
        int arr[nmemb];

        memset(arr, 0, ARRAY_BYTES(arr));
}

memset() এটির তৃতীয় আর্গুমেন্ট হিসাবে এই মানটির প্রয়োজন।

আগের মতো, যদি অ্যারেটি প্যারামিটার (পয়েন্টার) হিসাবে গ্রহণ করা হয় তবে এটি সংকলন করে না এবং আমাদের ম্যাক্রো কলটি মান দ্বারা প্রতিস্থাপন করতে হবে:

void foo(ptrdiff_t nmemb, int arr[nmemb])
{

        memset(arr, 0, sizeof(arr[0]) * nmemb);
}

আপডেট (23 / এপ্রিল / 2020): -Wsizeof-pointer-divবগি :

আজ আমি জানতে পেরেছি যে জিসিসিতে নতুন সতর্কতা কেবলমাত্র তখনই কাজ করে যদি ম্যাক্রো একটি শিরোনামে সিস্টেম শিরোনাম নয় in আপনি যদি আপনার সিস্টেমে (সাধারণত /usr/local/include/বা /usr/include/) ( #include <foo.h>) ইনস্টলড থাকা শিরোনামে ম্যাক্রো সংজ্ঞায়িত করেন তবে সংকলক কোনও সতর্কতা ছাড়বে না (আমি জিসিসি 9.3.0 চেষ্টা করেছি)।

সুতরাং আমাদের আছে #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))এবং এটি নিরাপদ করতে চাই। আমাদের _Static_assert()সি 11 এবং কিছু জিসিসি এক্সটেনশনগুলির দরকার হবে : এক্সপ্রেশনগুলিতে বিবৃতি এবং ঘোষণা , __ বিল্টিন_টাইপস_সামগ্রী_পি :

#define is_same_type(a, b)      __builtin_types_compatible_p(typeof(a), typeof(b))
#define is_array(a)             (!is_same_type((a), &(a)[0]))
#define Static_assert_array(a)  _Static_assert(is_array(a), "Not a `[]` !")

#define ARRAY_SIZE(arr)         (                                       \
{                                                                       \
        Static_assert_array(arr);                                       \
        sizeof(arr) / sizeof((arr)[0]);                                \
}                                                                       \
)

এখন ARRAY_SIZE()সম্পূর্ণ নিরাপদ, এবং তাই এর সমস্ত ডেরাইভেটিভস নিরাপদ থাকবে।


আপডেট: libbsd সরবরাহ করে __arraycount():

Libbsd ম্যাক্রো সরবরাহ __arraycount()করে <sys/cdefs.h>, যা অনিরাপদ কারণ এটিতে এক জোড়া বন্ধনী অভাব রয়েছে, তবে আমরা নিজেরাই সেই প্রথম বন্ধনী যুক্ত করতে পারি, এবং তাই আমাদের শিরোনামে বিভাগও লেখার প্রয়োজন নেই (কেন আমরা ইতিমধ্যে বিদ্যমান কোডটির নকল করব? )। এই ম্যাক্রোটি একটি সিস্টেম শিরোনামে সংজ্ঞায়িত করা হয়, সুতরাং আমরা যদি এটি ব্যবহার করি তবে আমরা উপরের ম্যাক্রোগুলি ব্যবহার করতে বাধ্য হব।

#include <sys/cdefs.h>


#define is_same_type(a, b)      __builtin_types_compatible_p(typeof(a), typeof(b))
#define is_array(a)             (!is_same_type((a), &(a)[0]))
#define Static_assert_array(a)  _Static_assert(is_array(a), "Not a `[]` !")

#define ARRAY_SIZE(arr)         (                                       \
{                                                                       \
        Static_assert_array(arr);                                       \
        __arraycount((arr));                                            \
}                                                                       \
)

#define ARRAY_SSIZE(arr)        ((ptrdiff_t)ARRAY_SIZE(arr))
#define ARRAY_BYTES(arr)        (sizeof((arr)[0]) * ARRAY_SIZE(arr))

কিছু সিস্টেম প্রদান nitems()মধ্যে <sys/param.h>পরিবর্তে, এবং কিছু ব্যবস্থা উভয় প্রদান। আপনার সিস্টেমটি পরীক্ষা করা উচিত, এবং আপনার একটিটি ব্যবহার করা উচিত, এবং সম্ভবত বহনযোগ্যতা এবং উভয় সমর্থন করার জন্য কিছু প্রিপ্রসেসর শর্তাদি ব্যবহার করুন।


আপডেট: ম্যাক্রোটিকে ফাইল স্কোপে ব্যবহারের অনুমতি দিন:

দুর্ভাগ্যক্রমে, ({})জিসিসি এক্সটেনশনটি ফাইল স্কোপে ব্যবহার করা যাবে না। ফাইল স্কোপে ম্যাক্রো ব্যবহার করতে সক্ষম হতে স্ট্যাটিক দৃ as়তা অবশ্যই ভিতরে থাকা উচিত sizeof(struct {})। তারপরে, 0ফলাফলকে প্রভাবিত না করার জন্য এটি দিয়ে গুণ করুন । কোনও কাস্ট (int)একটি ফাংশন যা ফেরত দেয় তা সিমুলেট করা ভাল হতে পারে (int)0(এই ক্ষেত্রে এটি প্রয়োজন হয় না তবে এটি অন্যান্য জিনিসের জন্য পুনরায় ব্যবহারযোগ্য)।

#include <sys/cdefs.h>


#define is_same_type(a, b)      __builtin_types_compatible_p(typeof(a), typeof(b))
#define is_array(a)             (!is_same_type((a), &(a)[0]))
#define Static_assert_array(a)  _Static_assert(is_array(a), "Not a `[]` !")
#define must_be_array(a)        (                                       \
        0 * (int)sizeof(                                                \
                struct {                                                \
                        Static_assert_array(a);                         \
                        char ISO_C_forbids_a_struct_with_no_members__;  \
                }                                                       \
        )                                                               \
)

#define ARRAY_SIZE(arr)         (__arraycount((arr)) + must_be_array(arr))
#define ARRAY_SSIZE(arr)        ((ptrdiff_t)ARRAY_SIZE(arr))
#define ARRAY_BYTES(arr)        (sizeof((arr)[0]) * ARRAY_SIZE(arr))

3
আপনি ডাউনটা কেন ব্যাখ্যা করতে আপত্তি করবেন? এ থেকে জানা যায় একটি অনিরাপদ এবং সাধারণ নির্মাণ (একটি সমাধান sizeof(arr)) যে অন্যত্র দেখানো হয় না: ARRAY_BYTES(arr)
ক্যাকাহুয়েত ফ্রিটো

2
ARRAY_SIZE অবাধে ব্যবহারের জন্য যথেষ্ট সাধারণ, এবং এর নামে ARRAY_BYTES খুব স্পষ্ট, এটি ARRAY_SIZE এর পাশে সংজ্ঞায়িত করা উচিত যাতে কোনও ব্যবহারকারী উভয়ই সহজেই দেখতে পায় এবং এর ব্যবহারের দ্বারা, আমি মনে করি না যে কোডটি পড়ে কারও কি সম্পর্কে সন্দেহ আছে এটা করে. আমি যা বোঝাতে চেয়েছি তা হল একটি সরল ব্যবহার না করা sizeof, তবে পরিবর্তে এই নির্মাণগুলি ব্যবহার করা; আপনি যদি এই নির্মাণগুলি প্রতিবার লেখার মতো মনে করেন তবে আপনি সম্ভবত ভুল করবেন (আপনি পেস্ট অনুলিপি করলে খুব সাধারণ এবং আপনি যখন প্রতিটি বার লিখেন তবে খুব সাধারণ কারণ তাদের প্রচুর বন্ধনী রয়েছে) ...
ক্যাকাহুয়েটি ফ্রেটো

3
..., তাই আমি মূল উপসংহারে দাঁড়িয়েছি: একটি এককটি sizeofপরিষ্কারভাবে অনিরাপদ (কারণগুলির উত্তরে রয়েছে), এবং ম্যাক্রোগুলি ব্যবহার না করে আমি যে নির্মাণগুলি প্রতিবার সরবরাহ করেছি তা ব্যবহার করে আরও বেশি অনিরাপদ, তাই যাওয়ার একমাত্র উপায় ম্যাক্রোজ হয়।
কাকাহুয়েত ফ্রিটো

3
@ মার্কহারিসন আমি পয়েন্টার এবং অ্যারের মধ্যে পার্থক্য জানি know তবে এমন একটি সময় হয়েছে যা আমি পরে সামান্য ফাংশনগুলিতে রিফ্যাক্ট করেছিলাম, এবং প্রথমে কোন অ্যারেটি ছিল তা পরে একটি পয়েন্টার ছিল এবং এটি এমন একটি বিষয় যেখানে আপনি যদি আকার পরিবর্তন করতে ভুলে যান তবে আপনি এটি স্ক্রু করেন এবং এটি সহজে দেখা যায় না সেগুলোর মধ্যে একটি.
ক্যাকাহুয়েত ফ্রিটো

3
@ হাইড এছাড়াও আমি জানি যে পার্থক্যটি এর অর্থ সবাই পার্থক্য জানে না এবং কেন এমন কিছু ব্যবহার করবেন না যা মূলত এই বাগগুলির 100% মুছে ফেলে? এই বাগটি এটি প্রায় লিনাক্সে পরিণত করেছিল; এটি লিনাসে পৌঁছেছে যার অর্থ এটি অনেকগুলি তদন্ত করে গেছে, এবং এর অর্থ হ'ল একই বাগটি কার্নেলের অন্য অংশে লিনাক্সে পরিণত করার সম্ভাবনা রয়েছে, যেমনটি তিনি বলেছিলেন।
কাকাহুতে ফ্রেটো

11

"আপনি নিজেকে পায়ে গুলি করার একটি সূক্ষ্ম উপায় চালু করেছেন"

সি 'নেটিভ' অ্যারেগুলি তাদের আকার সংরক্ষণ করে না। সুতরাং অ্যারের দৈর্ঘ্যটি একটি পৃথক ভেরিয়েবল / কনস্টেতে সংরক্ষণ করার পরামর্শ দেওয়া হয় এবং আপনি যখনই অ্যারে পাস করেন তখন তা পাস করুন, এটি হ'ল:

#define MY_ARRAY_LENGTH   15
int myArray[MY_ARRAY_LENGTH];

আপনি সর্বদা নেটিভ অ্যারেগুলি এড়ানো উচিত (যদি না আপনি পারেন না, তবে এক্ষেত্রে আপনার পায়ে বিবেচনা করুন)। আপনি যদি সি ++ লিখছেন তবে এসটিএল এর 'ভেক্টর' ধারকটি ব্যবহার করুন । "অ্যারের তুলনায় তারা প্রায় একই কর্মক্ষমতা সরবরাহ করে" এবং এগুলি আরও কার্যকর!

// vector is a template, the <int> means it is a vector of ints
vector<int> numbers;  

// push_back() puts a new value at the end (or back) of the vector
for (int i = 0; i < 10; i++)
    numbers.push_back(i);

// Determine the size of the array
cout << numbers.size();

দেখুন: http://www.cplusplus.com/references/stl/vector/


আমি পড়েছি যে সি তে পূর্ণসংখ্যার ধ্রুবক ঘোষণার সঠিক উপায় হ'ল একটি enumঘোষণা ব্যবহার করা ।
রাফি খ্যাচাডৌড়িয়ান

প্রশ্নটি সি ++ নয়, সি সম্পর্কে about সুতরাং কোনও এসটিএল নেই।
ক্যাকাহুয়েত ফ্রিটো


5

আপনি যদি আপনার অ্যারের কাছাকাছি যেতে সত্যিই এটি করতে চান তবে আমি আপনার বিন্যাসের যে ধরণের অ্যারে চান সেটি এবং অ্যারের আকারের প্রতিনিধিত্বকারী একটি পূর্ণসংখ্যা সংরক্ষণ করার জন্য একটি কাঠামো বাস্তবায়নের পরামর্শ দিচ্ছি। তারপরে আপনি এটি আপনার কার্যক্রমে পাস করতে পারেন। কেবলমাত্র সেই বিন্দুতে অ্যারে ভেরিয়েবল মান (পয়েন্টার প্রথম উপাদানটির জন্য) নির্ধারণ করুন। তারপরে আপনি Array.arr[i]আই-থ উপাদানটি পেতে যেতে পারেন Array.sizeএবং অ্যারের উপাদানগুলির সংখ্যা পেতে ব্যবহার করতে পারেন।

আমি আপনার জন্য কিছু কোড অন্তর্ভুক্ত করেছি। এটি খুব কার্যকর নয় তবে আপনি আরও বৈশিষ্ট্য সহ এটি প্রসারিত করতে পারেন। যদিও সত্য বলতে হবে, আপনি যদি এই জিনিসগুলি চান তবে আপনার সি ব্যবহার করা বন্ধ করা উচিত এবং অন্তর্নির্মিত এই বৈশিষ্ট্যগুলির সাথে অন্য কোনও ভাষা ব্যবহার করা উচিত।

/* Absolutely no one should use this...
   By the time you're done implementing it you'll wish you just passed around
   an array and size to your functions */
/* This is a static implementation. You can get a dynamic implementation and 
   cut out the array in main by using the stdlib memory allocation methods,
   but it will work much slower since it will store your array on the heap */

#include <stdio.h>
#include <string.h>
/*
#include "MyTypeArray.h"
*/
/* MyTypeArray.h 
#ifndef MYTYPE_ARRAY
#define MYTYPE_ARRAY
*/
typedef struct MyType
{
   int age;
   char name[20];
} MyType;
typedef struct MyTypeArray
{
   int size;
   MyType *arr;
} MyTypeArray;

MyType new_MyType(int age, char *name);
MyTypeArray newMyTypeArray(int size, MyType *first);
/*
#endif
End MyTypeArray.h */

/* MyTypeArray.c */
MyType new_MyType(int age, char *name)
{
   MyType d;
   d.age = age;
   strcpy(d.name, name);
   return d;
}

MyTypeArray new_MyTypeArray(int size, MyType *first)
{
   MyTypeArray d;
   d.size = size;
   d.arr = first;
   return d;
}
/* End MyTypeArray.c */


void print_MyType_names(MyTypeArray d)
{
   int i;
   for (i = 0; i < d.size; i++)
   {
      printf("Name: %s, Age: %d\n", d.arr[i].name, d.arr[i].age);
   }
}

int main()
{
   /* First create an array on the stack to store our elements in.
      Note we could create an empty array with a size instead and
      set the elements later. */
   MyType arr[] = {new_MyType(10, "Sam"), new_MyType(3, "Baxter")};
   /* Now create a "MyTypeArray" which will use the array we just
      created internally. Really it will just store the value of the pointer
      "arr". Here we are manually setting the size. You can use the sizeof
      trick here instead if you're sure it will work with your compiler. */
   MyTypeArray array = new_MyTypeArray(2, arr);
   /* MyTypeArray array = new_MyTypeArray(sizeof(arr)/sizeof(arr[0]), arr); */
   print_MyType_names(array);
   return 0;
}

1
strcpy(d.name, name);ওভারফ্লো হ্যান্ডলিংয়ের সাহায্যে কোড আপভোট করা যায় না ।
chux -

4

সর্বোত্তম উপায় হ'ল আপনি এই তথ্যটি সংরক্ষণ করুন, উদাহরণস্বরূপ, কোনও কাঠামোয়:

typedef struct {
     int *array;
     int elements;
} list_s;

প্রয়োজনীয়তা তৈরি করুন, ধ্বংস করুন, সাম্যতা যাচাই করুন এবং আপনার প্রয়োজন মতো সমস্ত কিছু কার্যকর করুন। প্যারামিটার হিসাবে পাস করা সহজ।


6
int elementsবনামের কোনও কারণ size_t elements?
chux - মনিকা

3

ফাংশনটি sizeofমেমরিতে আপনার অ্যারে দ্বারা ব্যবহৃত বাইটের সংখ্যা প্রদান করে। আপনি যদি আপনার অ্যারেতে উপাদানের সংখ্যা গণনা করতে চান তবে আপনার সেই সংখ্যাটি অ্যারের sizeofচলক প্রকারের সাথে ভাগ করা উচিত । ধরা যাক int array[10];, যদি আপনার কম্পিউটারে ভেরিয়েবল টাইপ পূর্ণসংখ্যা 32 বিট (বা 4 বাইট) হয় তবে আপনার অ্যারের আকার পেতে হলে আপনার নিম্নলিখিতটি করা উচিত:

int array[10];
int sizeOfArray = sizeof(array)/sizeof(int);

2

আপনি &অপারেটর ব্যবহার করতে পারেন । উত্স কোডটি এখানে:

#include<stdio.h>
#include<stdlib.h>
int main(){

    int a[10];

    int *p; 

    printf("%p\n", (void *)a); 
    printf("%p\n", (void *)(&a+1));
    printf("---- diff----\n");
    printf("%zu\n", sizeof(a[0]));
    printf("The size of array a is %zu\n", ((char *)(&a+1)-(char *)a)/(sizeof(a[0])));


    return 0;
};

এখানে নমুনা আউটপুট

1549216672
1549216712
---- diff----
4
The size of array a is 10

7
আমি নীচে নামি নি, তবে এটি একটি ইট দিয়ে পেরেক আঘাত করার মতো কারণ আপনি পাশে একটি হাতুড়ি পড়ে থাকতে দেখেছেন। এছাড়াও, লোকেরা অবিচ্ছিন্ন ভেরিয়েবলগুলি ব্যবহার করার বিষয়ে ঝুঁকির ঝোঁক রাখে ... তবে এখানে আমি অনুমান করি এটি আপনার উদ্দেশ্যটি যথেষ্ট পরিমাণে কার্যকর করে।
দিমিত্রি

2
@ দিমিত্রি এখানে বিনা অনিচ্ছাকৃত ভেরিয়েবলগুলি অ্যাক্সেস করতে পারে
এমএম

1
হুম। পয়েন্টার বিয়োগ বাড়ে ptrdiff_tsizeof()ফলাফল size_t। সি কোন বৃহত্তর বা উচ্চতর / একই পদমর্যাদার তা নির্ধারণ করে না । সুতরাং ভাগফলের ধরণটি ((char *)(&a+1)-(char *)a)/(sizeof(a[0]))অবশ্যই না size_tএবং এইভাবে মুদ্রণের ফলে zইউবি হতে পারে। সহজভাবে ব্যবহার printf("The size of array a is %zu\n", sizeof a/sizeof a[0]);করা যথেষ্ট।
chux - মনিকা

1
(char *)(&a+1)-(char *)aস্থির নয় এবং রান-টাইমে গণনা করা যেতে পারে এমনকি স্থির আকারের সাথেও a[10]sizeof(a)/sizeof(a[0])এই ক্ষেত্রে সংকলন সময়ে ধ্রুবক করা হয়।
chux - মনিকা পুনরায় ইনস্টল করুন

1

সহজ উত্তর:

#include <stdio.h>

int main(void) {

    int a[] = {2,3,4,5,4,5,6,78,9,91,435,4,5,76,7,34};//for Example only
    int size;

    size = sizeof(a)/sizeof(a[0]);//Method

    printf ("size = %d",size);
    return 0;
}


0

ইতিমধ্যে সরবরাহ করা উত্তরগুলির পাশাপাশি, আমি এর ব্যবহার দ্বারা একটি বিশেষ কেসটি নির্দেশ করতে চাই

sizeof(a) / sizeof (a[0])

aহয় হয় যদি একটি অ্যারে হয় char, unsigned charবা signed charআপনাকে এই জাতীয় ধরণের একটি অপারেন্ডের সাথে sizeofএকটি sizeofঅভিব্যক্তি সবসময় ফলস্বরূপ ব্যবহার করার প্রয়োজন হয় না 1

C18,6.5.3.4 / 4 এর উদ্ধৃতি:

" যখন sizeofকোন অপেরান্ড টাইপ আছে প্রয়োগ করা হয় char, unsigned charঅথবা signed char, (বা উহার একজন যোগ্যতাসম্পন্ন সংস্করণ) ফল 1।"

সুতরাং, টাইপের একটি অ্যারে হলে sizeof(a) / sizeof (a[0])সমান হবে , বা । 1 এর মাধ্যমে বিভাজন নিরর্থক।NUMBER OF ARRAY ELEMENTS / 1acharunsigned charsigned char

এই ক্ষেত্রে, আপনি কেবল সংক্ষিপ্ত বিবরণ এবং করতে পারেন:

sizeof(a)

উদাহরণ স্বরূপ:

char a[10];
size_t length = sizeof(a);

আপনি যদি প্রমাণ চান তবে এখানে গডবোল্টের লিঙ্ক ।


তবুও, বিভাগটি সুরক্ষা বজায় রাখে, যদি প্রকারটি উল্লেখযোগ্যভাবে পরিবর্তিত হয় (যদিও এই ক্ষেত্রেগুলি বিরল)।


1
আপনি সম্ভবত বিভাগের সাথে এখনও একটি ম্যাক্রো প্রয়োগ করতে পছন্দ করেন, কারণ ভবিষ্যতে প্রকারটি পরিবর্তিত হতে পারে (যদিও সম্ভবত সম্ভাবনা নেই), এবং বিভাগটি সংকলন সময়ে জানা যায়, তাই সংকলক এটিকে অপ্টিমাইজ করবে (যদি এটি পরিবর্তন না করে তবে) আপনার সংকলক)।
ক্যাকাহুয়েত ফ্রিটো

1
@ ক্যাকাহুয়েটফ্রিটো হ্যাঁ, আমি এর মধ্যেও ভেবেছিলাম। আমি এটি উত্তরের পার্শ্ব নোট হিসাবে গ্রহণ করেছি। ধন্যবাদ.
রবার্টস মনিকা সেলিও

-1

দ্রষ্টব্য: এই মন্তব্যে এমএম দ্বারা নির্দেশিত হিসাবে এটি আপনাকে অপরিবর্তিত আচরণ দিতে পারে।

int a[10];
int size = (*(&a+1)-a) ;

আরও তথ্যের জন্য এখানে এবং এখানে দেখুন


2
এটি প্রযুক্তিগতভাবে অপরিবর্তিত আচরণ; *অপারেটর একটি অতীত-শেষ পয়েন্টার প্রয়োগ করা যেতে পারে
এম এম

3
"অপরিবর্তিত আচরণ" এর অর্থ সি স্ট্যান্ডার্ড আচরণটি সংজ্ঞায়িত করে না। আপনি যদি আপনার প্রোগ্রামটিতে চেষ্টা করে থাকেন তবে কিছু ঘটতে পারে
এমএম

@MM আপনি বলছেন *(&a+1) - a;থেকে ভিন্ন (&a)[1] - a;সর্বোপরি, না উভয় *(&a+1)এবং (&a)[1]1 শেষে গত যেমন গণনা?
কোয়ান্টিনুক

@ কন্টিনিউক আপনার দুটি এক্সপ্রেশন দুটিই একই, x[y]হিসাবে সংজ্ঞায়িত করা হয়েছে*(x + (y))
এমএম

@ এমএম আমি ভেবেছিলাম তবে অর্জুন শ্রীধরনের অন্য উত্তরটির 38 টি তীর রয়েছে এবং এটি -1 রয়েছে। আর অর্জুন শ্রীধরনের জবাবে অপরিবর্তিত আচরণের কোনও উল্লেখ নেই।
কোয়ান্টিনুক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.