আমি সিটিতে আমার অ্যারের আকারটি কীভাবে নির্ধারণ করব?
অর্থাৎ অ্যারে কতগুলি উপাদান ধারণ করতে পারে?
আমি সিটিতে আমার অ্যারের আকারটি কীভাবে নির্ধারণ করব?
অর্থাৎ অ্যারে কতগুলি উপাদান ধারণ করতে পারে?
উত্তর:
নির্বাহী সারসংক্ষেপ:
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);
ARRAYSIZE
ম্যাক্রো সংজ্ঞায়িত করা আছে WinNT.h
(যা অন্য শিরোলেখ দ্বারা টানা হয়)। সুতরাং WinAPI ব্যবহারকারীদের তাদের নিজস্ব ম্যাক্রো সংজ্ঞায়িত করার দরকার নেই।
static int a[20];
। তবে আপনার মন্তব্য পাঠকদের পক্ষে দরকারী যা কোনও অ্যারে এবং পয়েন্টারের মধ্যে পার্থক্য বুঝতে পারে না।
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
length of parameter:2
যদি ১ ম অ্যারে এলিমেন্টের কেবলমাত্র একটি পয়েন্টার পাস হয়?
(sizeof array / sizeof *array)
।
এটি sizeof
একটি পয়েন্টারের কাছে ক্ষয় হয়ে যাওয়া অ্যারের মানের সাথে কাজ করার সময় সাহায্য করে না: এটি অ্যারের শুরুতে নির্দেশ করে, সংকলকটিতে এটি যে অ্যারের একক উপাদানের পয়েন্টার হিসাবে একই । পয়েন্টার অ্যারে যা আরম্ভ করার জন্য ব্যবহৃত হয়েছিল সে সম্পর্কে অন্য কিছু মনে রাখে না।
int a[10];
int* p = a;
assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));
char
32 টি বিট সহ সি ছিল । সমস্ত মান বলে যে 0 থেকে 127 পর্যন্ত পূর্ণসংখ্যার মানগুলি উপস্থাপিত হতে পারে এবং এর পরিসীমা কমপক্ষে -127 থেকে 127 (চর স্বাক্ষরিত) বা 0 থেকে 255 (চর স্বাক্ষরযুক্ত নয়) either
"ট্রিক" আকারটি আমি জানি সবচেয়ে ভাল উপায়, একটি ছোট কিন্তু (আমার কাছে এটি একটি বড় পোষা প্রাইভ হিসাবে) প্রথম বন্ধনী ব্যবহারের ক্ষেত্রে গুরুত্বপূর্ণ পরিবর্তন।
উইকিপিডিয়া এন্ট্রি যেমন পরিষ্কার করে দেয়, সি এর 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);
। এখানে, বন্ধনীগুলি সম্পূর্ণ নিখুঁতভাবে নান্দনিক।
sizeof
সর্বদা সি ++ এবং সি 89 এ ধ্রুব থাকবে। C99 এর পরিবর্তনশীল দৈর্ঘ্যের অ্যারে সহ, এটি রানটাইম সময়ে মূল্যায়ন করা যেতে পারে।
sizeof
অপারেটর হতে পারে তবে লিনাস টরভাল্ডস অনুসারে এটি একটি ফাংশন হিসাবে বিবেচিত হওয়া উচিত। আমি রাজী. তার যৌক্তিকতা এখানে পড়ুন: lkML.org/lkML/2012/7/11/103
int size = (&arr)[1] - arr;
ব্যাখ্যার জন্য এই লিঙ্কটি দেখুন
ptrdiff_t
। (সাধারণত 64৪-বিট সিস্টেমে এটির চেয়ে বড় ধরণের হবে int
)। এমনকি যদি আপনি পরিবর্তন int
করতে ptrdiff_t
এই কোডে, এটা এখনও একটি বাগ যদি গেছে arr
অ্যাড্রেস স্পেস অর্ধেকের বেশি লাগে।
/3G
বিকল্পের সাথে আপনার 3 জি / 1 জি ব্যবহারকারী / কার্নেল বিভাজন রয়েছে, যা আপনাকে ঠিকানা স্থানের আকারের 75% পর্যন্ত অ্যারে আকার দিতে দেয়।
foo buf1[80]; foo buf2[sizeof buf1/sizeof buf1[0]]; foo buf3[(&buf1)[1] - buf1];
গ্লোবাল ভেরিয়েবল হিসাবে বিবেচনা করুন । buf3[]
ঘোষণা যেমন (&buf1)[1] - buf1
একটি ধ্রুবক নয় ত্রুটিযুক্ত ।
আপনি আকারের অপারেটরটি ব্যবহার করতে পারেন তবে এটি ফাংশনগুলির জন্য কাজ করবে না কারণ এটি বিন্যাসের রেফারেন্স নেবে আপনি কোনও অ্যারের দৈর্ঘ্য সন্ধান করতে নিম্নলিখিতটি করতে পারেন:
len = sizeof(arr)/sizeof(arr[0])
কোডটি মূলত এখানে পাওয়া গেছে: একটি অ্যারেতে উপাদানের সংখ্যা খুঁজতে সি প্রোগ্রাম
আপনি যদি অ্যারের ডাটা টাইপটি জানেন তবে আপনি এমন কিছু ব্যবহার করতে পারেন:
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
(অ্যারের নাম) একটি পয়েন্টার।
int noofele = sizeof(arr)/sizeof(int);
কোডিংয়ের চেয়ে আধ-রাস্তা ভাল int noofele = 9;
। ব্যবহার করে sizeof(arr)
নমনীয়তা বজায় রাখে অ্যারের আকার পরিবর্তন হওয়া উচিত। তবুও পরিবর্তনের sizeof(int)
ধরণের উচিত একটি আপডেট দরকার arr[]
। sizeof(arr)/sizeof(arr[0])
প্রকারটি ভাল জানা থাকলেও ব্যবহার করা ভাল। কেন ব্যবহার অস্পষ্ট int
জন্য noofele
বনাম size_t
টাইপ দ্বারা ফিরে sizeof()
।
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
হিসাবে একটি পয়েন্টার টাইপ হিসাবে শেষ হবে এবং পুরো ম্যাক্রো অকার্যকর (ঠিক যেমন আপনি একটি পয়েন্টার প্যারামিটার সহ একটি ফাংশনে ম্যাক্রো ব্যবহার করার চেষ্টা করেছেন)।
দিনের শেষে, এই বিশেষ উদাহরণে, দোষটি আসলেই কিছু যায় আসে না (তাই আমি কেবল প্রত্যেকের সময় নষ্ট করছি; হুজ্জা!), কারণ আপনার এক ধরণের 'অ্যারে' দিয়ে অভিব্যক্তি নেই। তবে প্রকৃতপক্ষে প্রিপ্রোসেসর মূল্যায়ন সাবটেলগুলি সম্পর্কে আমি মনে করি এটি একটি গুরুত্বপূর্ণ।
(sizeof (x) / sizeof (*x))
?
জন্য বহুমাত্রিক অ্যারে এটা একটি বাচ্চা জটিল। প্রায়শই লোকেরা সুস্পষ্ট ম্যাক্রো কনস্ট্যান্টগুলি সংজ্ঞায়িত করে, যেমন
#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])
ইত্যাদি।
sizeof(array) / sizeof(array[0])
array
, আপনি উভয়ের একটি অ্যারে sizeof(array) / sizeof(array[0])
হলে ব্যবহার করার প্রয়োজন নেই , বা - C18,6.5.3.4 / 4 থেকে উদ্ধৃতি: "যখন আকারটি কোনও অপরেন্ডে প্রয়োগ করা হয় যেখানে টাইপ চর, স্বাক্ষরবিহীন চর বা স্বাক্ষর করা চর রয়েছে , (বা এর একটি যোগ্য সংস্করণ) ফলাফলটি ১। " এই ক্ষেত্রে আপনি আমার উত্সর্গীকৃত উত্তরে বর্ণিত হিসাবে সহজভাবে করতে পারেন । array
char
unsigned char
signed char
sizeof(array)
সি তে একটি অ্যারের আকার:
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
size_t size_of_element
int
int n = sizeof (a) / sizeof (a[0]);
size_t n = sizeof (a) / sizeof (a[0]);
char a[INT_MAX + 1u];
, int n
যেমন ব্যবহৃত int n = sizeof (a) / sizeof (a[0]);
যথেষ্ট নয় (এটা UB যায়)। ব্যবহার size_t n = sizeof (a) / sizeof (a[0]);
করে এই সমস্যা হয় না।
আমি 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);
}
-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()
সম্পূর্ণ নিরাপদ, এবং তাই এর সমস্ত ডেরাইভেটিভস নিরাপদ থাকবে।
__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))
sizeof(arr)
) যে অন্যত্র দেখানো হয় না: ARRAY_BYTES(arr)
।
sizeof
, তবে পরিবর্তে এই নির্মাণগুলি ব্যবহার করা; আপনি যদি এই নির্মাণগুলি প্রতিবার লেখার মতো মনে করেন তবে আপনি সম্ভবত ভুল করবেন (আপনি পেস্ট অনুলিপি করলে খুব সাধারণ এবং আপনি যখন প্রতিটি বার লিখেন তবে খুব সাধারণ কারণ তাদের প্রচুর বন্ধনী রয়েছে) ...
sizeof
পরিষ্কারভাবে অনিরাপদ (কারণগুলির উত্তরে রয়েছে), এবং ম্যাক্রোগুলি ব্যবহার না করে আমি যে নির্মাণগুলি প্রতিবার সরবরাহ করেছি তা ব্যবহার করে আরও বেশি অনিরাপদ, তাই যাওয়ার একমাত্র উপায় ম্যাক্রোজ হয়।
"আপনি নিজেকে পায়ে গুলি করার একটি সূক্ষ্ম উপায় চালু করেছেন"
সি 'নেটিভ' অ্যারেগুলি তাদের আকার সংরক্ষণ করে না। সুতরাং অ্যারের দৈর্ঘ্যটি একটি পৃথক ভেরিয়েবল / কনস্টেতে সংরক্ষণ করার পরামর্শ দেওয়া হয় এবং আপনি যখনই অ্যারে পাস করেন তখন তা পাস করুন, এটি হ'ল:
#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();
enum
ঘোষণা ব্যবহার করা ।
#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0]))
আপনি যদি আপনার অ্যারের কাছাকাছি যেতে সত্যিই এটি করতে চান তবে আমি আপনার বিন্যাসের যে ধরণের অ্যারে চান সেটি এবং অ্যারের আকারের প্রতিনিধিত্বকারী একটি পূর্ণসংখ্যা সংরক্ষণ করার জন্য একটি কাঠামো বাস্তবায়নের পরামর্শ দিচ্ছি। তারপরে আপনি এটি আপনার কার্যক্রমে পাস করতে পারেন। কেবলমাত্র সেই বিন্দুতে অ্যারে ভেরিয়েবল মান (পয়েন্টার প্রথম উপাদানটির জন্য) নির্ধারণ করুন। তারপরে আপনি 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;
}
strcpy(d.name, name);
ওভারফ্লো হ্যান্ডলিংয়ের সাহায্যে কোড আপভোট করা যায় না ।
সর্বোত্তম উপায় হ'ল আপনি এই তথ্যটি সংরক্ষণ করুন, উদাহরণস্বরূপ, কোনও কাঠামোয়:
typedef struct {
int *array;
int elements;
} list_s;
প্রয়োজনীয়তা তৈরি করুন, ধ্বংস করুন, সাম্যতা যাচাই করুন এবং আপনার প্রয়োজন মতো সমস্ত কিছু কার্যকর করুন। প্যারামিটার হিসাবে পাস করা সহজ।
int elements
বনামের কোনও কারণ size_t elements
?
ফাংশনটি sizeof
মেমরিতে আপনার অ্যারে দ্বারা ব্যবহৃত বাইটের সংখ্যা প্রদান করে। আপনি যদি আপনার অ্যারেতে উপাদানের সংখ্যা গণনা করতে চান তবে আপনার সেই সংখ্যাটি অ্যারের sizeof
চলক প্রকারের সাথে ভাগ করা উচিত । ধরা যাক int array[10];
, যদি আপনার কম্পিউটারে ভেরিয়েবল টাইপ পূর্ণসংখ্যা 32 বিট (বা 4 বাইট) হয় তবে আপনার অ্যারের আকার পেতে হলে আপনার নিম্নলিখিতটি করা উচিত:
int array[10];
int sizeOfArray = sizeof(array)/sizeof(int);
আপনি &
অপারেটর ব্যবহার করতে পারেন । উত্স কোডটি এখানে:
#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
ptrdiff_t
। sizeof()
ফলাফল 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]);
করা যথেষ্ট।
(char *)(&a+1)-(char *)a
স্থির নয় এবং রান-টাইমে গণনা করা যেতে পারে এমনকি স্থির আকারের সাথেও a[10]
। sizeof(a)/sizeof(a[0])
এই ক্ষেত্রে সংকলন সময়ে ধ্রুবক করা হয়।
আরও মার্জিত সমাধান হবে
size_t size = sizeof(a) / sizeof(*a);
ইতিমধ্যে সরবরাহ করা উত্তরগুলির পাশাপাশি, আমি এর ব্যবহার দ্বারা একটি বিশেষ কেসটি নির্দেশ করতে চাই
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 / 1
a
char
unsigned char
signed char
এই ক্ষেত্রে, আপনি কেবল সংক্ষিপ্ত বিবরণ এবং করতে পারেন:
sizeof(a)
উদাহরণ স্বরূপ:
char a[10];
size_t length = sizeof(a);
আপনি যদি প্রমাণ চান তবে এখানে গডবোল্টের লিঙ্ক ।
তবুও, বিভাগটি সুরক্ষা বজায় রাখে, যদি প্রকারটি উল্লেখযোগ্যভাবে পরিবর্তিত হয় (যদিও এই ক্ষেত্রেগুলি বিরল)।
দ্রষ্টব্য: এই মন্তব্যে এমএম দ্বারা নির্দেশিত হিসাবে এটি আপনাকে অপরিবর্তিত আচরণ দিতে পারে।
int a[10];
int size = (*(&a+1)-a) ;
আরও তথ্যের জন্য এখানে এবং এখানে দেখুন ।
*
অপারেটর একটি অতীত-শেষ পয়েন্টার প্রয়োগ করা যেতে পারে
*(&a+1) - a;
থেকে ভিন্ন (&a)[1] - a;
সর্বোপরি, না উভয় *(&a+1)
এবং (&a)[1]
1 শেষে গত যেমন গণনা?
x[y]
হিসাবে সংজ্ঞায়িত করা হয়েছে*(x + (y))