C හි මගේ අරාවේ ප්රමාණය තීරණය කරන්නේ කෙසේද?
එනම්, අරාව සතුව තිබිය හැකි මූලද්රව්ය ගණන?
C හි මගේ අරාවේ ප්රමාණය තීරණය කරන්නේ කෙසේද?
එනම්, අරාව සතුව තිබිය හැකි මූලද්රව්ය ගණන?
Answers:
විධායක සාරාංශය:
int a[17];
size_t n = sizeof(a)/sizeof(a[0]);
සම්පූර්ණ පිළිතුර:
ඔබේ අරාවෙහි ප්රමාණය බයිට් වලින් තීරණය කිරීමට, ඔබට sizeof
ක්රියාකරු භාවිතා කළ හැකිය :
int a[17];
size_t n = sizeof(a);
මගේ පරිගණකයේ, ints දිග බයිට් 4 ක් වන බැවින් n 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];
. නමුත් ඔබේ අදහස පා readers කයන්ට ප්රයෝජනවත් වන අතර එය අරාව සහ දර්ශකය අතර වෙනස නොදැනේ.
මෙම sizeof
මාර්ගය නිවැරදි මාර්ගය වේ යන සැකය ඔබට පරාමිතීන් ලෙස ලැබී නැත පෙලගැස්මක් සමඟ කටයුතු කර ඇත. ශ්රිතයකට පරාමිතියක් ලෙස යවන ලද අරාව දර්ශකයක් ලෙස සලකනු ලැබේ, එබැවින් 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
1 වන අරාවෙහි මූලද්රව්යයට දර්ශකයක් පමණක් ලබා දෙන්නේ නම් ඇයි ?
(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 දක්වා (වර්ගය අත්සන් නොකෙරේ).
"උපක්රමය" ප්රමාණය මා දන්නා හොඳම ක්රමය වන අතර, එක් කුඩා නමුත් (මට නම් මෙය ප්රධාන සුරතල් සතෙකු වීම) වරහන් භාවිතා කිරීමේ වැදගත් වෙනසක් ඇත.
විකිපීඩියා ප්රවේශය පැහැදිලි කරන පරිදි, C හි sizeof
ශ්රිතයක් නොවේ; එය ක්රියාකරුවෙකි . මේ අනුව, තර්කය වර්ග නාමයක් නම් මිස, එහි තර්කය වටා වරහන් අවශ්ය නොවේ. මෙය මතක තබා ගැනීම පහසුය, මන්ද එය තර්කය වාත්තු ප්රකාශනයක් මෙන් පෙනෙන අතර වරහන් ද භාවිතා කරයි.
ඉතින්: ඔබට පහත සඳහන් දෑ තිබේ නම්:
int myArray[10];
මේ වගේ කේත සහිත මූලද්රව්ය ගණන ඔබට සොයාගත හැකිය:
size_t n = sizeof myArray / sizeof *myArray;
එය, වරහන් සමඟ ඇති විකල්පයට වඩා බොහෝ පහසුවෙන් කියවිය හැකිය. කොට් of ාශයේ දකුණු පසෙහි තරු ලකුණ භාවිතා කිරීමට මම කැමැත්තෙමි, මන්ද එය සුචිගත කිරීමට වඩා සංක්ෂිප්ත ය.
ඇත්ත වශයෙන්ම, මේ සියල්ල සම්පාදනය කරන වේලාව ද වේ, එබැවින් වැඩසටහනේ ක්රියාකාරීත්වයට බලපාන බෙදීම ගැන කරදර විය යුතු නැත. එබැවින් ඔබට හැකි සෑම තැනකම මෙම පෝරමය භාවිතා කරන්න.
ඔබ වර්ගයක් මත නොව සත්ය වස්තුවක් මත ඇති විට එය භාවිතා කිරීම වඩාත් සුදුසුය, එතැන් සිට ඔබ වැරැද්දක් කිරීම සහ වැරදි වර්ගය සඳහන් කිරීම ගැන කරදර විය යුතු නැත.
නිදසුනක් ලෙස, ඔබට සමහර දත්ත බයිට් ප්රවාහයක් ලෙස ප්රතිදානය කරන ශ්රිතයක් ඇති බව පවසන්න, උදාහරණයක් ලෙස ජාලයක් හරහා. අපි ශ්රිතය අමතමු 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
සෑම විටම C ++ සහ C89 වල නියත වනු ඇත. C99 හි විචල්ය දිග අරා සමඟ, එය ධාවන වේලාවේදී ඇගයීමට ලක් කළ හැකිය.
sizeof
ක්රියාකරුවෙකු විය හැකි නමුත් එය ලිනස් ටොවල්ඩ්ස් අනුව ශ්රිතයක් ලෙස සැලකිය යුතුය. මම එකඟයි. ඔහුගේ තාර්කිකත්වය මෙතැනින් කියවන්න: lkml.org/lkml/2012/7/11/103
int size = (&arr)[1] - arr;
පැහැදිලි කිරීම සඳහා මෙම සබැඳිය බලන්න
ptrdiff_t
ඇත. (සාමාන්යයෙන් 64-බිට් පද්ධතියේ, මෙය වඩා විශාල වර්ගයක් වනු ඇත int
). ඔබ මෙම කේතයට වෙනස් int
කළත් , ලිපින අවකාශයෙන් අඩකට වඩා ගත ptrdiff_t
වුවහොත් එයට දෝෂයක් arr
ඇත.
/3G
ඔබට 3G / 1G පරිශීලක / කර්නල් බෙදීමක් ඇත, එමඟින් ලිපින අවකාශයේ ප්රමාණයෙන් 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", " " },
};
එහෙත්, මේ නියත සමග ද එක්රැස් කාලීන ඇගැයීමට ලක් කළ හැකි sizeof :
#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);
මෙම කේතය C සහ C ++ වලින් ක්රියාත්මක වන බව සලකන්න. මානයන් දෙකකට වඩා ඇති අරා සඳහා භාවිතා කරන්න
sizeof(name[0][0][0])
sizeof(name[0][0][0][0])
ආදිය, දැන්වීම් අනන්තය.
C හි අරාවක ප්රමාණය:
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(array) / sizeof(array[0])
array
, ඔබ විසින් අරාවක් sizeof(array) / sizeof(array[0])
තිබේ නම් භාවිතා කිරීමට අවශ්ය array
නොවේ char
, unsigned char
හෝ signed char
- C18,6.5.3.4 / 4 වෙතින් උපුටා ගැනීම: “වර්ගයේ වර්ග, අත්සන් නොකළ වරහන් හෝ අත්සන් කළ වර්ග සහිත ඔපෙරන්ඩ් එකකට ප්රමාණයේ ප්රමාණය යොදන විට , (හෝ එහි සුදුසුකම් ලත් අනුවාදයක්) ප්රති result ලය 1. ” මෙම අවස්ථාවේදී ඔබට sizeof(array)
මගේ කැපවූ පිළිතුරෙන් පැහැදිලි කළ පරිදි සරලව කළ හැකිය .
මා sizeof
මෙහි පෙන්වන අවසාන අවස්ථා දෙක වන මූලද්රව්ය ගණනකින් හෝ බයිට් වලින් හෝ අරාවෙහි විවිධ ප්රමාණ දෙකෙන් එකක් ලබා ගැනීමට කිසි විටෙකත් භාවිතා නොකරන ලෙස (එය භාවිතා කළ හැකි වුවද) මම උපදෙස් දෙමි. එක් එක් ප්රමාණ දෙක සඳහා, පහත දැක්වෙන මැක්රෝස් එය ආරක්ෂිත කිරීමට භාවිතා කළ හැකිය. හේතුව නඩත්තුකරන්නන් කිරීමට කේතය, හා වෙනස කිරීමේ අරමුණින් පැහැදිලි කිරීමයි sizeof(ptr)
සිට sizeof(arr)
දෝෂ පසුව කේතය කියවන සියල්ලන්ම සඳහා පැහැදිලි ය එසේ බව, (ලියන ලද මෙම මාර්ගය පැහැදිලිව හඳුනාගත නොහැකි වන) බැලූ බැල්මට.
ටීඑල්; ඩීආර්:
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + Static_assert_eval0_array(arr))
#define ARRAY_SSIZE(arr) ((ptrdiff_t)ARRAY_SIZE(arr))
#define ARRAY_BYTES(arr) (sizeof((arr)[0]) * ARRAY_SIZE(arr))
Static_assert_eval0_array(arr)
(පහත අර්ථ දක්වා ඇත) -Wsizeof-pointer-div
දෝෂ සහිත ලෙස අයිඑස් අවශ්ය වේ (අප්රේල් / 2020 අනුව):
#define Static_assert_eval0(e, ...) ( \
0 * (int)sizeof( \
struct { \
_Static_assert((e) __VA_OPT__(,) __VA_ARGS__);\
char ISO_C_forbids_a_struct_with_no_members__; \
} \
) \
)
#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_eval0_array(a) Static_assert_eval0(is_array(a), "Not a `[]` !")
මෙම මාතෘකාව සම්බන්ධයෙන් වැදගත් දෝෂ තිබේ: 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 හි ප්රති result ලය අත්සන් කරන ලද විචල්යයන් සමඟ බහුලව භාවිතා වන හෙයින්, මෙම සාර්වයේ ptrdiff_t
අත්සන් කළ ප්රභේදයක් නිර්වචනය කිරීම හොඳ ය:
#define ARRAY_SSIZE(arr) ((ptrdiff_t)ARRAY_SIZE(arr))
PTRDIFF_MAX
සාමාජිකයින්ට වඩා වැඩි සංඛ්යාවක් ඇති සාර්ව වල අත්සන් කරන ලද මෙම අනුවාදය සඳහා අවලංගු අගයන් ලබා දීමට යන්නේ, නමුත් C17 :: 6.5.6.9 කියවීමෙන්, එවැනි අරා දැනටමත් ගින්නෙන් සෙල්ලම් කරයි. එකම ARRAY_SIZE
හා size_t
එම අවස්ථාවල දී භාවිතා කළ යුතුය.
GCC 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
ඉදිකිරීම් වල අමතර ආරක්ෂාව සමඟ ය .
භාවිතයේ උදාහරණය:
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
දෝෂ සහිතයි :අද මම දැනගත්තා GCC හි නව අනතුරු ඇඟවීම ක්රියාත්මක වන්නේ පද්ධති ශීර්ෂයක් නොවන ශීර්ෂයක සාර්ව අර්ථ දක්වා ඇත්නම් පමණි. ඔබේ පද්ධතියේ (සාමාන්යයෙන් /usr/local/include/
හෝ /usr/include/
) ( #include <foo.h>
) ස්ථාපනය කර ඇති ශීර්ෂයක ඔබ සාර්ව අර්ථ දක්වන්නේ නම් , සම්පාදකයා අනතුරු ඇඟවීමක් නොකරයි (මම GCC 9.3.0 උත්සාහ කළෙමි).
එබැවින් අපට #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
එය ආරක්ෂිත කිරීමට අවශ්යය. අපට C11 _Static_assert()
සහ සමහර GCC දිගු අවශ්ය වේ: ප්රකාශනවල ප්රකාශ සහ ප්රකාශන , __builtin_types_compatible_p :
#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>
, ඒ වෙනුවට, හා සමහර පද්ධති දෙකම සපයයි. ඔබ ඔබේ පද්ධතිය පරික්ෂා කළ යුතු අතර, ඔබ සතුව ඇති ක්රමය භාවිතා කළ යුතු අතර, අතේ ගෙන යා හැකි සහ පෙර සැකසුම් සඳහා පෙර සැකසුම් කොන්දේසි කිහිපයක් භාවිතා කරන්න.
අවාසනාවට, ({})
ගොනු විෂය පථයේ gcc දිගුව භාවිතා කළ නොහැක. ලිපිගොනු විෂය පථයේ සාර්ව භාවිතා කිරීමට නම්, ස්ථිතික ප්රකාශය ඇතුළත තිබිය යුතුය sizeof(struct {})
. ඉන්පසු ප්රති 0
result ලයට බලපෑමක් නොවන පරිදි එය ගුණ කරන්න . (int)
නැවත පැමිණෙන ශ්රිතයක් අනුකරණය කිරීම සඳහා වාත්තු කිරීම හොඳ විය හැකිය (int)0
(මේ අවස්ථාවේ දී එය අවශ්ය නොවේ, නමුත් එය වෙනත් දේ සඳහා නැවත භාවිතා කළ හැකිය).
#include <sys/cdefs.h>
#define Static_assert_eval0(e, ...) ( \
0 * (int)sizeof( \
struct { \
_Static_assert((e) __VA_OPT__(,) __VA_ARGS__);\
char ISO_C_forbids_a_struct_with_no_members__; \
} \
) \
)
#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_eval0_array(a) Static_assert_eval0(is_array(a), "Not a `[]` !")
#define ARRAY_SIZE(arr) (__arraycount((arr)) + Static_assert_eval0_array(arr))
#define ARRAY_SSIZE(arr) ((ptrdiff_t)ARRAY_SIZE(arr))
#define ARRAY_BYTES(arr) (sizeof((arr)[0]) * ARRAY_SIZE(arr))
මෙම කේතය පහත සඳහන් දිගු භාවිතා කරයි, ඒවා සම්පූර්ණයෙන්ම අවශ්ය වන අතර ඒවායේ පැවැත්ම ආරක්ෂාව සඳහා අත්යවශ්ය වේ. ඔබේ සම්පාදකයා සතුව ඒවා හෝ ඒ හා සමාන ඒවා නොමැති නම්, ඔබට මෙම මට්ටමේ ආරක්ෂාව ලබා ගත නොහැක.
මම පහත දැක්වෙන C11 විශේෂාංගය ද භාවිතා කරමි. කෙසේ වෙතත්, පැරණි ප්රමිතියක් භාවිතා කිරීමෙන් එය නොපැවතීම සමහර අපිරිසිදු උපක්රම භාවිතා කර ජය ගත හැකිය (උදාහරණයක් ලෙස බලන්න: සී කේතයේ “: - !!” යනු කුමක්ද? ).
මම පහත දිගුව ද භාවිතා කරමි, නමුත් එකම දේ කිරීමට සම්මත C ක්රමයක් ඇත.
sizeof(arr)
වෙනත් තැනක නොපෙන්වන අනාරක්ෂිත සහ පොදු ඉදිකිරීම් සඳහා විසඳුමක් පෙන්වයි : ARRAY_BYTES(arr)
.
sizeof
, ඒ වෙනුවට මෙම ඉදිකිරීම් භාවිතා කරන්න; සෑම විටම මෙම ඉදිකිරීම් ලිවීමට ඔබට හැඟේ නම්, ඔබ වැරැද්දක් කරනු ඇත (ඔබ පේස්ට් පිටපත් කරන්නේ නම් එය ඉතා සුලභ ය, තවද වරහන් විශාල ප්රමාණයක් ඇති බැවින් ඔබ ඒවා සෑම විටම ලියන්නේ නම්) ...
sizeof
එකක් පැහැදිලිවම අනාරක්ෂිත ය (හේතු පිළිතුරේ ඇත), මැක්රෝස් භාවිතා නොකොට මා විසින් සපයන ලද ඉදිකිරීම් භාවිතා කිරීම, සෑම අවස්ථාවකදීම ඊටත් වඩා අනාරක්ෂිත ය, එබැවින් යා හැකි එකම මාර්ගය මැක්රෝස් වේ.
"ඔබ පාදයට වෙඩි තැබීමේ සියුම් ක්රමයක් හඳුන්වා දී ඇත"
සී 'ස්වදේශීය' අරා ඒවායේ ප්රමාණය ගබඩා නොකරයි. එබැවින් අරාවෙහි දිග වෙනම විචල්යයක / සංයුක්තයක සුරැකීම රෙකමදාරු කරනු ලැබේ, ඔබ අරාව පසු කරන සෑම විටම එය සම්මත කරන්න, එනම්:
#define MY_ARRAY_LENGTH 15
int myArray[MY_ARRAY_LENGTH];
ඔබ සැමවිටම ස්වදේශික අරා වලින් වැළකී සිටිය යුතුය (ඔබට නොහැකි නම්, ඔබේ පාදය මතක තබා ගන්න). ඔබ C ++ ලියන්නේ නම්, STL හි 'දෛශික' බහාලුම භාවිතා කරන්න. "අරා හා සසඳන විට, ඒවා එකම කාර්ය සාධනයක් සපයයි", ඒවා වඩාත් ප්රයෝජනවත් වේ!
// 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]
i-th මූලද්රව්යය 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()
ප්රති results ල size_t
. C යනු වඩා පුළුල් හෝ ඉහළ / එකම තරාතිරම කුමක්ද යන්න නිර්වචනය නොකරයි . එබැවින් උපුටා දැක්වීමේ ((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])
සමාන වනු ඇත NUMBER OF ARRAY ELEMENTS / 1
නම් a
වර්ගය රැසක් වේ char
, unsigned char
හෝ signed char
. 1 හරහා බෙදීම අතිරික්ත වේ.
මෙම අවස්ථාවේ දී, ඔබට හුදෙක් කෙටියෙන් හා කළ හැකිය:
sizeof(a)
උදාහරණයක් වශයෙන්:
char a[10];
size_t length = sizeof(a);
ඔබට සාක්ෂියක් අවශ්ය නම්, මෙන්න ගොඩ්බෝල්ට් වෙත සබැඳියක් .
එසේ වුවද, වර්ගය සැලකිය යුතු ලෙස වෙනස් වුවහොත් (මෙම අවස්ථා දුර්ලභ වුවද) අංශය ආරක්ෂාව පවත්වා ගනී.
සටහන: අදහස් දැක්වීමේදී එම්.එම් පෙන්වා දුන් පරිදි මෙමඟින් ඔබට නිර්වචනය නොකළ හැසිරීමක් ලබා දිය හැකිය.
int a[10];
int size = (*(&a+1)-a) ;
වැඩි විස්තර සඳහා මෙහි සහ මෙහි බලන්න .
*
ක්රියාකරු ආදි-the-අවසන් හේතුවම යෙදිය නොහැකි විය හැක
*(&a+1) - a;
වෙනස් (&a)[1] - a;
, දෙකම *(&a+1)
සහ (&a)[1]
අවසානය 1 ලෙස ගණන් නොගන්න ?
x[y]
අර්ථ දැක්වෙන්නේ*(x + (y))