C හි මගේ අරාවේ ප්‍රමාණය තීරණය කරන්නේ කෙසේද?


Answers:


1292

විධායක සාරාංශය:

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);

6
සම්පාදකයා සම්පාදක වේලාවේදී * int_arr වර්ගය දන්නා බැවින් ජනනය කරන ලද කේතය සමාන වේ (එම නිසා ප්‍රමාණයේ වටිනාකම (* int_arr)). එය නියතයක් වනු ඇති අතර, සම්පාදකයාට ඒ අනුව ප්‍රශස්තිකරණය කළ හැකිය.
මාර්ක් හැරිසන්

10
ප්‍රමාණයේ ප්‍රති results ල සම්පාදක කාල නියතයක් ලෙස අර්ථ දක්වා ඇති බැවින් එය සියලු සම්පාදකයින්ගේ තත්වය විය යුතුය.
මාර්ක් හැරිසන්

463
වැදගත් : මෙහි කියවීම නවත්වන්න එපා, ඊළඟ පිළිතුර කියවන්න! මෙය ක්‍රියාත්මක වන්නේ තොගයේ අරා සඳහා පමණි , උදා: ඔබ malloc () භාවිතා කරන්නේ නම් හෝ ක්‍රියාකාරී පරාමිතියකට ප්‍රවේශ වන්නේ නම්, ඔබට වාසනාව නැත. පහත බලන්න.
මාකස්

7
සී හෝ සී ++ හි වින්ඩෝස් ඒපීඅයි වැඩසටහන්කරණය සඳහා, ARRAYSIZEඅර්ථ දක්වා ඇති මැක්‍රෝ ඇත WinNT.h(එය වෙනත් ශීර්ෂයන් විසින් ඇද ගනු ලැබේ). එබැවින් WinAPI භාවිතා කරන්නන්ට තමන්ගේම මැක්‍රෝ නිර්වචනය කිරීමට අවශ්‍ය නොවේ.
ලුමි

17
Ark මාකස් එය අරාව වර්ගයක් ඇති ඕනෑම විචල්‍යයක් සඳහා ක්‍රියා කරයි; මෙය "තොගයේ" තිබිය යුතු නොවේ. උදා static int a[20];. නමුත් ඔබේ අදහස පා readers කයන්ට ප්‍රයෝජනවත් වන අතර එය අරාව සහ දර්ශකය අතර වෙනස නොදැනේ.
එම්එම්

824

මෙම 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

10
length of parameter:21 වන අරාවෙහි මූලද්‍රව්‍යයට දර්ශකයක් පමණක් ලබා දෙන්නේ නම් ඇයි ?
Bbvarghe

16
BBbvarghe එයට හේතුව 64bit පද්ධතිවල දර්ශක බයිට් 8 ක් (ප්‍රමාණයෙන් (intArray)), නමුත් ints තවමත් (සාමාන්‍යයෙන්) බයිට් 4 ක් දිග (ප්‍රමාණයෙන් (intArray [0])).
එලිඩෙබ්

13
Ac පැකේරියර්: නිවැරදි කේතයක් නොමැත - සාමාන්‍ය විසඳුම වන්නේ අරාව සමඟ දිග වෙනම තර්කයක් ලෙස සම්මත කිරීමයි.
ජීන් හෝමිනල්

10
රැඳී සිටින්න, එබැවින් දර්ශකයකින් කෙලින්ම අරාව වෙත පිවිසීමට සහ එහි ප්‍රමාණය බැලීමට ක්‍රමයක් නොමැතිද? සී ට අළුත්.
sudo

7
Ic මයිකල් ට්‍ර rou ව්: ඔබට හොඳ හැඟීමක් ඇති වුවහොත් ඔබට ක්‍රියාකරු සින්ටැක්ස් භාවිතා කළ හැකිය : (sizeof array / sizeof *array).
chqrlie

137

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
@ මැග්නස්: ප්‍රමිතිය ප්‍රමාණයෙන් අර්ථ දක්වන්නේ වස්තුවේ බයිට් ගණන ලබා දෙන අතර ප්‍රමාණය (වර්‍ගය) සෑම විටම එකකි. බයිට් එකක බිටු ගණන ක්‍රියාත්මක කිරීම විශේෂිත වේ. සංස්කරණය කරන්න: ANSI C ++ සම්මත අංශය 5.3.3 ප්‍රමාණය: “ප්‍රමාණයේ ක්‍රියාකරු එහි ක්‍රියාකාරිත්වයේ වස්තු නිරූපණයෙහි බයිට් ගණන ලබා දෙයි. 1; වෙනත් ඕනෑම මූලික වර්ගයකට අදාළ වන ප්‍රමාණයේ ප්‍රති result ලය ක්‍රියාත්මක කිරීම-අර්ථ දක්වා ඇත.
ස්කීස්

1.6 වන කොටස සී ++ මතක ආකෘතිය: "සී ++ මතක ආකෘතියේ මූලික ගබඩා ඒකකය බයිට් වේ. මූලික ක්‍රියාත්මක කිරීමේ අක්ෂර කට්ටලයේ ඕනෑම සාමාජිකයෙකු අඩංගු කිරීමට තරම් අවම වශයෙන් බයිට් එකක් විශාල වන අතර එය අනුක්‍රමික බිටු අනුක්‍රමයකින් සමන්විත වේ. ඒවා ක්‍රියාත්මක කිරීම අර්ථ දක්වා ඇත.
ස්කීස්

2
මට මතකයි CRAY හි C charබිටු 32 ක් ඇති බව. සියලු ප්‍රමිතීන් පවසන්නේ 0 සිට 127 දක්වා පූර්ණ සංඛ්‍යා අගයන් නිරූපණය කළ හැකි අතර එහි පරාසය අවම වශයෙන් -127 සිට 127 දක්වා (වර්‍ග අත්සන් කර ඇත) හෝ 0 සිට 255 දක්වා (වර්‍ගය අත්සන් නොකෙරේ).
වොන්බ්‍රෑන්ඩ්

5
මෙය විශිෂ්ට ප්‍රතිචාරයකි. ඉහත ප්‍රකාශ සියල්ලම සත්‍ය ලෙස ඇගයීමට ලක් කර ඇති බව මට අදහස් දැක්වීමට අවශ්‍යය.
ජාවඩ්

49

"උපක්‍රමය" ප්‍රමාණය මා දන්නා හොඳම ක්‍රමය වන අතර, එක් කුඩා නමුත් (මට නම් මෙය ප්‍රධාන සුරතල් සතෙකු වීම) වරහන් භාවිතා කිරීමේ වැදගත් වෙනසක් ඇත.

විකිපීඩියා ප්‍රවේශය පැහැදිලි කරන පරිදි, 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);

දැන් ඔබව ආරක්ෂා කර ඇත. නිසැකවම, ඔබ විචල්යයේ නම අනුපිටපත් කරයි, නමුත් එය වෙනස් කරන්නේ නම්, සම්පාදකයාට හඳුනාගත හැකි ආකාරයකින් කැඩී යාමේ ඉහළ සම්භාවිතාවක් ඇත.


Btw, ඒවා ප්‍රොසෙසර් මට්ටමින් සමාන උපදෙස්ද? වන්නේද, sizeof(int)වඩා අඩු උපදෙස් අවශ්ය sizeof(foo)?
පැසීරියර්

Ac පැකේරියර්: නැත, ඒවා සමාන වේ. int x = 1+1;එදිරිව සිතන්න int x = (1+1);. මෙන්න, වරහන් යනු හුදෙක් සෞන්දර්යාත්මක ය.
quetzalcoatl

IdAidiakapi එය සත්‍ය නොවේ, C99 VLAs සලකා බලන්න.
ලිහිල්

ස්තූතියි, මම නිවැරදි කරමි. මගේ අදහස නිවැරදි කිරීම සඳහා, sizeofසෑම විටම C ++ සහ C89 වල නියත වනු ඇත. C99 හි විචල්ය දිග අරා සමඟ, එය ධාවන වේලාවේදී ඇගයීමට ලක් කළ හැකිය.
අයිඩියාකාපි

2
sizeofක්‍රියාකරුවෙකු විය හැකි නමුත් එය ලිනස් ටොවල්ඩ්ස් අනුව ශ්‍රිතයක් ලෙස සැලකිය යුතුය. මම එකඟයි. ඔහුගේ තාර්කිකත්වය මෙතැනින් කියවන්න: lkml.org/lkml/2012/7/11/103
වෛද්‍ය පුද්ගලයා II

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

පැහැදිලි කිරීම සඳහා මෙම සබැඳිය බලන්න


7
කුඩා නයිට්පික්: දර්ශක අඩු කිරීමේ ප්‍රති result ලය වර්ගය ptrdiff_tඇත. (සාමාන්‍යයෙන් 64-බිට් පද්ධතියේ, මෙය වඩා විශාල වර්ගයක් වනු ඇත int). ඔබ මෙම කේතයට වෙනස් intකළත් , ලිපින අවකාශයෙන් අඩකට වඩා ගත ptrdiff_tවුවහොත් එයට දෝෂයක් arrඇත.
එම්එම්

2
@MM තවත් කුඩා නට්පික් එකක්: ඔබේ පද්ධති සැකැස්ම අනුව, ලිපින අවකාශය බොහෝ පද්ධතිවල දර්ශක ප්‍රමාණය තරම් විශාල නොවේ. වින්ඩෝස් උදාහරණයක් ලෙස බිට් 64 යෙදුම් සඳහා ලිපින අවකාශය 8TB හෝ බිට් 44 දක්වා සීමා කරයි. එබැවින් ඔබගේ ලිපින අවකාශයේ අඩකට වඩා විශාල අරාවක් ඔබ සතුව තිබුණද 4.1TB, එය දෝෂයක් නොවනු ඇත. එම පද්ධතිවල ඔබගේ ලිපින අවකාශය බිටු 63 ඉක්මවා ගියහොත් පමණක්, එවැනි දෝෂයකට පවා මුහුණ දිය හැකිය. පොදුවේ, ඒ ගැන කරදර නොවන්න.
අයිඩියාකාපි

1
IdAidiakapi 32-bit x86 ලිනක්ස් මත හෝ වින්ඩෝස් හි /3Gඔබට 3G / 1G පරිශීලක / කර්නල් බෙදීමක් ඇත, එමඟින් ලිපින අවකාශයේ ප්‍රමාණයෙන් 75% ක් දක්වා අරා ප්‍රමාණයක් තිබිය හැක.
රුස්ලාන්

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",        " " },
};

එහෙත්, මේ නියත සමග ද එක්රැස් කාලීන ඇගැයීමට ලක් කළ හැකි 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])

ආදිය, දැන්වීම් අනන්තය.


16

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

4
කේතයක් භාවිතා බව කුතුහලයෙන් size_t size_of_elementතවමත් intසමග int n = sizeof (a) / sizeof (a[0]); නොවsize_t n = sizeof (a) / sizeof (a[0]);
නැවත සේවයේ පිහිටුවීමට මොනිකා - chux

1
හායි @ යෝගීෂ් එච්ටී, කරුණාකර චක්ස් පිළිබඳ සැකයට පිළිතුරු දිය හැකිද? Int n = sizeof (a) / sizeof (a [0]) අරාවෙහි දිග ලබා දෙන්නේ කෙසේද සහ අරාවෙහි දිග සඳහා අපි size_t භාවිතා නොකරන්නේ ඇයිද යන්න දැන ගැනීමටද මට කුතුහලයක් ඇත. කිසිවෙකුට එයට පිළිතුරු දිය හැකිද?
මොළය

1
Ra බ්‍රේන් ප්‍රමාණය (අ) අරාවෙහි ඇති සියලුම මූලද්‍රව්‍යවල ප්‍රමාණයෙන් විශාල ප්‍රමාණයක් ලබා දෙයි (a [0]) 1 වන මූලද්‍රව්‍යවල ප්‍රමාණය ලබා දෙයි. A = {1,2,3,4,5} යැයි සිතමු; sizeof (a) = 20 බයිට් (sizeof (int) = 4 බයිට් 5 ගුණ කළහොත්), sizeof (a [0]) = 4 බයිට්, එබැවින් 20/4 = 5 එනම් මූලද්‍රව්‍ය කිසිවක් නැත
Yogeesh HT

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 - මොනිකා නැවත ස්ථාපනය කරන්න

15
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)මගේ කැපවූ පිළිතුරෙන් පැහැදිලි කළ පරිදි සරලව කළ හැකිය .
රොබට්ස් විසින් මොනිකා සෙලියෝ

15

මා 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);
}

යාවත්කාලීන කිරීම (23 / apr / 2020): -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()සම්පූර්ණයෙන්ම ආරක්ෂිතයි, එබැවින් එහි සියලු ව්‍යුත්පන්නයන් ආරක්ෂිත වනු ඇත.


යාවත්කාලීන කිරීම: 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>, ඒ වෙනුවට, හා සමහර පද්ධති දෙකම සපයයි. ඔබ ඔබේ පද්ධතිය පරික්ෂා කළ යුතු අතර, ඔබ සතුව ඇති ක්‍රමය භාවිතා කළ යුතු අතර, අතේ ගෙන යා හැකි සහ පෙර සැකසුම් සඳහා පෙර සැකසුම් කොන්දේසි කිහිපයක් භාවිතා කරන්න.


යාවත්කාලීන කිරීම: ගොනු විෂය පථයට සාර්ව භාවිතා කිරීමට ඉඩ දෙන්න:

අවාසනාවට, ({})ගොනු විෂය පථයේ gcc දිගුව භාවිතා කළ නොහැක. ලිපිගොනු විෂය පථයේ සාර්ව භාවිතා කිරීමට නම්, ස්ථිතික ප්‍රකාශය ඇතුළත තිබිය යුතුය sizeof(struct {}). ඉන්පසු ප්‍රති 0result ලයට බලපෑමක් නොවන පරිදි එය ගුණ කරන්න . (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 ක්‍රමයක් ඇත.


3
පහත වැටීමට හේතුව පැහැදිලි කිරීමට ඔබ කැමතිද? මෙය sizeof(arr)වෙනත් තැනක නොපෙන්වන අනාරක්ෂිත සහ පොදු ඉදිකිරීම් සඳහා විසඳුමක් පෙන්වයි : ARRAY_BYTES(arr).
Cacahuete Frito

2
ARRAY_SIZE නිදහසේ භාවිතා කිරීමට තරම් පොදු වන අතර ARRAY_BYTES එහි නමින් ඉතා පැහැදිලිය, එය ARRAY_SIZE ට යාබදව අර්ථ දැක්විය යුතුය, එවිට පරිශීලකයාට දෙකම පහසුවෙන් දැකිය හැකි අතර, එහි භාවිතය අනුව, කේතය කියවන ඕනෑම කෙනෙකුට කුමක් ගැන සැකයක් ඇත්දැයි මම නොසිතමි. එය සිදු වේ. මා අදහස් කළේ සරල දෙයක් භාවිතා නොකිරීමයි sizeof, ඒ වෙනුවට මෙම ඉදිකිරීම් භාවිතා කරන්න; සෑම විටම මෙම ඉදිකිරීම් ලිවීමට ඔබට හැඟේ නම්, ඔබ වැරැද්දක් කරනු ඇත (ඔබ පේස්ට් පිටපත් කරන්නේ නම් එය ඉතා සුලභ ය, තවද වරහන් විශාල ප්‍රමාණයක් ඇති බැවින් ඔබ ඒවා සෑම විටම ලියන්නේ නම්) ...
Cacahuete Frito

3
..., එබැවින් මම ප්‍රධාන නිගමනයට එළඹ සිටිමි: තනි sizeofඑකක් පැහැදිලිවම අනාරක්ෂිත ය (හේතු පිළිතුරේ ඇත), මැක්‍රෝස් භාවිතා නොකොට මා විසින් සපයන ලද ඉදිකිරීම් භාවිතා කිරීම, සෑම අවස්ථාවකදීම ඊටත් වඩා අනාරක්ෂිත ය, එබැවින් යා හැකි එකම මාර්ගය මැක්‍රෝස් වේ.
Cacahuete Frito

3
Ark මාක් හැරිසන් දර්ශකයන් සහ අරා අතර වෙනස මම දනිමි. නමුත් මා සතුව ශ්‍රිතයක් ඇති අතර පසුව එය කුඩා කාර්යයන් බවට ප්‍රතිනිර්මාණය කරන ලද අතර, පළමුව අරාව යනු පසුකාලීනව දර්ශකයක් විය. එය එක් ලක්ෂ්‍යයක් නම් ඔබට ප්‍රමාණය වෙනස් කිරීමට අමතක වුවහොත් ඔබ එය ඉස්කුරුප්පු කරන අතර එය නොපෙනීම පහසුය ඒවායින් එකක්.
Cacahuete Frito

3
@hyde එසේම වෙනස මා දන්නා නිසා සෑම කෙනෙකුම වෙනස දන්නා බව අදහස් නොකෙරේ, එම දෝෂ වලින් 100% ක් මූලික වශයෙන් ඉවත් කරන දෙයක් භාවිතා නොකරන්නේ ඇයි? එම දෝෂය එය පාහේ ලිනක්ස් බවට පත් කළේය; එය ලිනස් වෙත පැමිණියේය, එයින් අදහස් කරන්නේ එය බොහෝ සෝදිසි කිරීම් සමත් වූ අතර, එයින් අදහස් වන්නේ ඔහු පවසන පරිදි එම දෝෂයම කර්නලයේ තවත් කොටසක ලිනක්ස් බවට පත්කිරීමේ හැකියාව පවතින බවයි.
Cacahuete Frito

11

"ඔබ පාදයට වෙඩි තැබීමේ සියුම් ක්‍රමයක් හඳුන්වා දී ඇත"

සී 'ස්වදේශීය' අරා ඒවායේ ප්‍රමාණය ගබඩා නොකරයි. එබැවින් අරාවෙහි දිග වෙනම විචල්‍යයක / සංයුක්තයක සුරැකීම රෙකමදාරු කරනු ලැබේ, ඔබ අරාව පසු කරන සෑම විටම එය සම්මත කරන්න, එනම්:

#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();

බලන්න: http://www.cplusplus.com/reference/stl/vector/


C හි පූර්ණ සංඛ්‍යා නියතයන් ප්‍රකාශ කිරීම සඳහා නිසි ක්‍රමය enumප්‍රකාශයක් භාවිතා කිරීම බව මම කියවා ඇත්තෙමි .
රෆි ඛට්චඩූරියන්

ප්‍රශ්නය C ගැන නොව C ++ ගැන ය. එබැවින් එස්.ටී.එල්.
Cacahuete Frito


5

ඔබේ අරාව වටා ගමන් කිරීම සඳහා ඔබට මෙය සැබවින්ම කිරීමට අවශ්‍ය නම්, මම ඔබට යෝජනා කරන්නේ ඔබට අරාව අවශ්‍ය වර්ගයට සහ අරාවෙහි විශාලත්වය නියෝජනය කරන පූර්ණ සංඛ්‍යාවක් සඳහා දර්ශකයක් ගබඩා කිරීම සඳහා ව්‍යුහයක් ක්‍රියාත්මක කිරීමට ය. එවිට ඔබට එය ඔබගේ කාර්යයන් වෙත යොමු කළ හැකිය. අර දර්ශකයට අරාව විචල්‍ය අගය (දර්ශකය පළමු මූලද්‍රව්‍යයට) පවරන්න. එවිට ඔබට 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;
}

1
strcpy(d.name, name);පිටාර ගැලීම හැසිරවීමකින් තොරව කේතය ඉහළ නැංවිය නොහැක .
chux - මොනිකා නැවත ස්ථාපනය කරන්න

4

හොඳම ක්‍රමය නම් ඔබ මෙම තොරතුරු ව්‍යුහයක් තුළ සුරැකීමයි:

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

නිර්මාණය කිරීම, විනාශ කිරීම, සමානාත්මතාවය පරීක්ෂා කිරීම සහ ඔබට අවශ්‍ය සියල්ල වැනි අවශ්‍ය සියලු කාර්යයන් ක්‍රියාත්මක කරන්න. පරාමිතියක් ලෙස සමත් වීම පහසුය.


6
int elementsඑදිරිව යම් හේතුවක් size_t elementsතිබේද?
chux - මොනිකා නැවත ස්ථාපනය කරන්න

4

ශ්‍රිතය 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_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]);කිරීම ප්රමාණවත්ය.
chux - මොනිකා නැවත ස්ථාපනය කරන්න

1
(char *)(&a+1)-(char *)aනියතයක් නොවන අතර ස්ථාවර ප්‍රමාණයේ වුවද ධාවන වේලාවේදී ගණනය කළ හැකිය a[10]. sizeof(a)/sizeof(a[0])මෙම අවස්ථාවේ දී සම්පාදනය කරන වේලාවේ නියත වේ.
chux - මොනිකා නැවත ස්ථාපනය කරන්න

2

සරලම පිළිතුර:

#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;
}


-1

දැනටමත් ලබා දී ඇති පිළිතුරු වලට අමතරව, භාවිතයෙන් විශේෂ අවස්ථාවක් පෙන්වා දීමට මට අවශ්‍යය

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);

ඔබට සාක්ෂියක් අවශ්‍ය නම්, මෙන්න ගොඩ්බෝල්ට් වෙත සබැඳියක් .


එසේ වුවද, වර්ගය සැලකිය යුතු ලෙස වෙනස් වුවහොත් (මෙම අවස්ථා දුර්ලභ වුවද) අංශය ආරක්ෂාව පවත්වා ගනී.


1
අනාගතයේදී වර්ගය වෙනස් විය හැකි නිසා (සමහර විට එය විය නොහැක්කකි), සහ බෙදීම් සම්පාදනය කරන වේලාවේදී දන්නා බැවින් සම්පාදකයා එය ප්‍රශස්තිකරණය කරනු ඇත (එය කරුණාකර වෙනස් නොවේ නම්) ඔබේ සම්පාදකයා).
Cacahuete Frito

1
AcCacahueteFrito ඔව්, මේ අතරතුර මමත් ඒ ගැන සිතුවෙමි. මම එය පැත්තක සටහනක් ලෙස පිළිතුරට ගත්තෙමි. ඔබට ස්තුතියි.
රොබට්ස් මොනිකා සෙලියෝට සහය දක්වයි

මම උපදෙස් දෙන්නේ කවදාවත් ඒ හොරෙන් වෙන්න එපා කියලයි. සම්පාදනය කරන වේලාවේදී බෙදීම සිදු කරන බැවින් එය කිසිදු කාර්ය සාධන වැඩිදියුණු කිරීම් එකතු නොකරයි.
Cacahuete Frito

-2

සටහන: අදහස් දැක්වීමේදී එම්.එම් පෙන්වා දුන් පරිදි මෙමඟින් ඔබට නිර්වචනය නොකළ හැසිරීමක් ලබා දිය හැකිය.

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

වැඩි විස්තර සඳහා මෙහි සහ මෙහි බලන්න .


2
මෙය තාක්‍ෂණිකව නිර්වචනය නොකළ හැසිරීමකි; මෙම *ක්රියාකරු ආදි-the-අවසන් හේතුවම යෙදිය නොහැකි විය හැක
එම්.එම්

3
“නිර්වචනය නොකළ හැසිරීම” යන්නෙන් සී ප්‍රමිතිය හැසිරීම නිර්වචනය නොකරයි. ඔබ එය ඔබගේ වැඩසටහන තුළ උත්සාහ කළහොත් ඕනෑම දෙයක් සිදුවිය හැකිය
MM

@ එම්එම් ඔබ කියන්නේ ඉහළින් වඩා *(&a+1) - a;වෙනස් (&a)[1] - a;, දෙකම *(&a+1)සහ (&a)[1]අවසානය 1 ලෙස ගණන් නොගන්න ?
QuentinUK

@QuentinUK ඔබේ ප්‍රකාශන දෙකම එක හා සමානයි, x[y]අර්ථ දැක්වෙන්නේ*(x + (y))
MM

@ එම්එම් මම එහෙම හිතුවා. නමුත් අනෙක් පිළිතුර, අර්ජුන් ශ්‍රීධරන් විසින් ඊතල 38 ක් ඇති අතර මෙයට -1 ඇත. අර්ජුන් ශ්‍රීධරන්ගේ පිළිතුරෙහි නිර්වචනය නොකළ හැසිරීම ගැන සඳහනක් නොමැත.
QuentinUK
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.