数组名的理解
一知识补充1数组名的两个例外我们知道单独的数组名arr表示的是数组首元素的地址但是有两个例外• sizeof(数组名)sizeof中单独放数组名这⾥的数组名表示整个数组计算的是整个数组的大小单位是字节(单独很重要如果sizeof中还有其他东西都不算单独)• 数组名这⾥的数组名表示整个数组取出的是整个数组的地址整个数组的地址和数组⾸元素的地址是有区别的除此之外任何地⽅使⽤数组名数组名都表示⾸元素的地址2数组首元素地址下面代码三个指针的值都是一样的但是需要理解各自的含义#include stdio.h int main() { int arr[10] { 1,2,3,4,5,6,7,8,9,10 }; printf(arr[0] %p\n, arr[0]); printf(arr %p\n, arr); printf(arr %p\n, arr); return 0; }解释①arr[0]是最好理解的就是取到了数组中第一个元素的地址所以类型肯定为int*②arr就是数组名此时不属于两个例外情况所以就是数组首元素地址类型为int*③arr属于例外情况此时取到的是整个数组的首地址类型为int(*)[10]注int(*)[10]中的*必须用()包起来提高优先级此时的*才是代表指针否则就会和前面的int结合代表该数组存储的是int*所以下面代码对三个地址分别进行1指针跳过的长度必然不一样#include stdio.h int main() { int arr[10] { 1,2,3,4,5,6,7,8,9,10 }; printf(arr[0] %p\n, arr[0]); printf(arr[0]1 %p\n, arr[0] 1); printf(arr %p\n, arr); printf(arr1 %p\n, arr 1); printf(arr %p\n, arr); printf(arr1 %p\n, arr 1); return 0; }解释①arr[0]和arr[0]1因为arr[0]类型为int* 所以arr[0]1跳过了4字节②arr和arr1因为arr类型为int*所以arr1跳过了4字节③arr和arr1因为arr取到的是整个数组的首地址类型为int(*)[10]所以跳过了整个数组字节大小也就是40个字节④图示如下3赋给char*的字符串char* p abcdef;注char * pabcdef 相当于把字符串abcdef的首地址给p了(并不是把abcdef放进了p里面)p代表首元素a的地址所以p1跳过的是a而不是整个字符串类比char arr[] abcdef;arr就是首元素的地址arr1跳过了a4sizeof和strlen1、用法不一样sizeof可以用类型(指针整形,数组等)做参数用来求一个类型的字节长度strlen只能用char*类型做参数且必须是以\0结尾的才能计算出准确的值否则是随机值另外strlen的参数不是char*类型的否则结果为error报错2、功能不一样sizeof的功能能是获得保证能容纳实现所建立的最大对象的字节大小。strlen的功能是返回字符串的长度该字符串可能是自己定义的也可能是内存中随机的该函数实际完成的功能是从代表该字符串的第一个地址开始遍历直到遇到结束符 \0 。返回的长度大小不包括 \0 。sizeof和strlen还有诸多的细节更多详细内容在如下博客中https://blog.csdn.net/shylyly_/article/details/160418711?spm1001.2014.3001.5501二题目讲解注指针在32位下(x86)指针为4字节64位下(x64)为8字节地址就是指针1sizeof整形一维数组解释①printf(%d\n, sizeof(arr))16数组名单独放在sizeof内部这里的a表示整个数组计算的是整个数组的大小单位是字节,总共16个字节②printf(%d\n, sizeof(a0))4/8因为数组名没有单独放在sizeof内部所以a表示数组首元素的地址a0仍是数组首元素的地址地址就是指针指针大小就是4/8个字节③printf(%d\n, sizeof(*a))4a数组名没有单独在sizeof中所以a表示数组首元素的地址,*a就是首元素,大小4个字节④printf(%d\n, sizeof(a1))4/8a数组名没有单独在sizeof中所以a表示数组首元素的地址a1是第二个元素的地址指针的大小为4/8。⑤printf(%d\n, sizeof( a[1] ))4第二个元素的大小就是4个字节⑥printf(%d\n,sizeof(a));4/8a是整个数组的地址但是整个数组的地址也就是一个指针所以大小4/8。⑦printf(%d\n,sizeof(*a));16sizeof*a中*抵消所以就变成了sizeof(a)此时数组名单独放在sizeof内部属于例外情况所以表示整个数组的大小所以16(虽然不是sizeof(数组名)但是*抵消就是)⑧printf(%d\n,sizeof(a1));4/8a1其中a是例外情况得到的是整个数组的首地址类型为int(*)[10]此时1直接跳过了整个数组但是即使跳过了整个数组a1依然是指针是地址就是4/8个字节。⑨printf(%d\n,sizeof(a[0]));4/8a[0]是取出了首元素的地址是指针大小就是4/8个字节。⑩printf(%d\n,sizeof(a[0]1));4/8a[0]是首元素的地址a[0]1就是第二个元素的地址是指针大小就是4/8。代码#include stdio.h int main() { //一维数组 int a[] { 1,2,3,4 }; // ①16数组名单独放在sizeof内部这里的a表示整个数组计算的是整个数组的大小单位是字节,总共16个字节 printf(%d\n, sizeof(a)); // ②4/8因为数组名没有单独放在sizeof内部所以a表示数组首元素的地址a0仍是数组首元素的地址地址就是指针指针大小就是4/8个字节 printf(%d\n, sizeof(a 0)); // ③4a数组名没有单独在sizeof中所以a表示数组首元素的地址,*a就是首元素,大小4个字节 printf(%d\n, sizeof(*a)); // ④4/8a数组名没有单独在sizeof中所以a表示数组首元素的地址a1是第二个元素的地址指针的大小为4/8 printf(%d\n, sizeof(a 1)); // ⑤4第二个元素的大小就是4个字节 printf(%d\n, sizeof(a[1])); // ⑥4/8a是整个数组的地址但是整个数组的地址也就是一个指针所以大小4/8 printf(%d\n, sizeof(a)); // ⑦16sizeof*a中*抵消所以就变成了sizeof(a)此时数组名单独放在sizeof内部属于例外情况所以表示整个数组的大小所以16 printf(%d\n, sizeof(*a)); // ⑧4/8a1其中a是例外情况得到的是整个数组的首地址类型为int(*)[4]此时1直接跳过了整个数组但是即使跳过了整个数组a1依然是指针是地址就是4/8个字节 printf(%d\n, sizeof(a 1)); // ⑨4/8a[0]是取出了首元素的地址是指针大小就是4/8个字节 printf(%d\n, sizeof(a[0])); // ⑩4/8a[0]是首元素的地址a[0]1就是第二个元素的地址是指针大小就是4/8 printf(%d\n, sizeof(a[0] 1)); }2sizeof字符数组(不含\0)解释①printf(%d\n, sizeof(arr));6数组名单独放在sizeof内部这里的arr表示整个数组计算的是整个数组的大小单位是字节,总共6个字节②printf(%d\n, sizeof(arr 0));4/8因为数组名没有单独放在sizeof内部所以arr表示数组首元素的地址arr0还是数组首元素的地址是指针就是4/8个字节③printf(%d\n, sizeof(*arr));1arr表示数组首元素的地址,*arr就是首元素首元素是a大小1个字节④printf(%d\n, sizeof(arr[1]));1arr[1]就是第二个元素b大小是1个字节⑤printf(%d\n, sizeof(arr));4/8arr是整个数组的首地址但是数组的地址也是地址是指针就是4/8个字节⑥printf(%d\n, sizeof(arr 1));4/8arr是整个数组的首地址arr 1是跳过整个数组后的地址是指针就是4/8个字节⑦printf(%d\n, sizeof(arr[0] 1));4/8arr[0]是取出第一个元素的地址然后1是第二个元素的地址是指针就是4/8个字节代码#include stdio.h int main() { //字符数组 char arr[] { a, b, c, d, e, f }; // ①6数组名单独放在sizeof内部这里的arr表示整个数组计算的是整个数组的大小单位是字节,总共6个字节 printf(%d\n, sizeof(arr)); // ②4/8因为数组名没有单独放在sizeof内部所以arr表示数组首元素的地址arr0还是数组首元素的地址是指针就是4/8个字节 printf(%d\n, sizeof(arr 0)); // ③1arr表示数组首元素的地址,*arr就是首元素首元素是a大小1个字节 printf(%d\n, sizeof(*arr)); // ④1arr[1]就是第二个元素b大小是1个字节 printf(%d\n, sizeof(arr[1])); // ⑤4/8arr是整个数组的首地址但是数组的地址也是地址是指针就是4/8个字节 printf(%d\n, sizeof(arr)); // ⑥4/8arr是整个数组的首地址arr 1是跳过整个数组后的地址是指针就是4/8个字节 printf(%d\n, sizeof(arr 1)); // ⑦4/8arr[0]是取出第一个元素的地址然后1是第二个元素的地址是指针就是4/8个字节 printf(%d\n, sizeof(arr[0] 1)); }3strlen字符数组(不含\0)解释①printf(%d\n, strlen(arr));随机值arr是数组首元素地址而因为字符数组arr中没有\0所以strlen会从数组最开始一直往后找不知道什么时候才找到\0产生的结果就是随机值②printf(%d\n, strlen(arr 0));随机值arr 0是首元素的地址和第一个一样由于没有\0也是随机值③printf(%d\n, strlen(*arr));error, arr是数组首元素的地址*arr就是数组首元素就是a-97类型为charstrlen函数参数的部分需要传一个char*类型不符报错本质是因为当我们传递的是a时a的ASCII码值是97strlen会将97作为地址传参strlen就会从97这个地址开始统计字符串长度这种行为通常是不允许的会导致报错④printf(%d\n, strlen(arr[1]));error因为arr[1]是数组的元素类型为char所以与3一致报错⑤printf(%d\n, strlen(arr));随机值arr是整个数组的首地址,但是整个数组的首地址和数组首元素的地址值是一样的传递给strlen函数后依然是从数组的第一个元素的位置开始往后统计由于没有\0所以也是随机值⑥printf(%d\n, strlen(arr 1));随机值arr 1代表越过了整个数组后的地址也是随机值不知道什么时候才能碰上 \0⑦printf(%d\n, strlen(arr[0] 1));随机值arr[0] 1是第二个元素的地址结果也是随机值代码#include stdio.h int main() { //字符数组 char arr[] { a,b,c,d,e,f }; // ①随机值arr是数组首元素地址而因为字符数组arr中没有\0所以strlen会从数组最开始一直往后找不知道什么时候才找到\0产生的结果就是随机值 printf(%d\n, strlen(arr)); // ②随机值arr 0是首元素的地址和第一个一样由于没有\0也是随机值 printf(%d\n, strlen(arr 0)); // ③errorarr是数组首元素的地址*arr就是数组首元素就是a-97类型为char // strlen函数参数的部分需要传一个char*类型不符报错 // 本质是因为当我们传递的是a时a的ASCII码值是97strlen会将97作为地址传参 // strlen就会从97这个地址开始统计字符串长度这种行为通常是不允许的会导致报错 printf(%d\n, strlen(*arr)); // 这行会编译报错或运行时崩溃 // ④error因为arr[1]是数组的元素类型为char所以与③一致报错 printf(%d\n, strlen(arr[1])); // 这行会编译报错或运行时崩溃 // ⑤随机值arr是整个数组的首地址但是整个数组的首地址和数组首元素的地址值是一样的 // 传递给strlen函数后依然是从数组的第一个元素的位置开始往后统计由于没有\0所以也是随机值 printf(%d\n, strlen(arr)); // ⑥随机值arr 1代表越过了整个数组后的地址也是随机值不知道什么时候才能碰上\0 printf(%d\n, strlen(arr 1)); // ⑦随机值arr[0] 1是第二个元素的地址结果也是随机值 printf(%d\n, strlen(arr[0] 1)); }4sizeof字符串数组解释①printf(%d\n, sizeof(arr));7因为除开6个元素\0 也会记入总计7个元素每个大小为1个字节②printf(%d\n, sizeof(arr 0));4/8arr是数组首元素地址arr 0仍是首元素的地址 是指针所以大小4/8③printf(%d\n, sizeof(*arr));1arr是数组首元素地址*arr就是首元素a,1个字节所以1也可以这么理解*arr-- *(arr0) --arr[0]④printf(%d\n, sizeof(arr[1]));1arr[1]是第二个元素b1个字节大小所以1⑤printf(%d\n, sizeof(arr));4/8arr是整个数组的首地址但是只要是指针就是4/8个字节⑥printf(%d\n, sizeof(arr 1));4/8arr是整个数组的首地址1跳过整个数组的地址但本质也是指针所以是4/8⑦printf(%d\n, sizeof(arr[0] 1));4/8arr[0]得到第一个元素的地址 1是第二个元素的地址是指针大小就是 4/8代码#includestdio.h int main() { char arr[] abcdef; // ①7因为除开6个元素\0也会记入总计7个元素每个大小为1个字节 printf(%d\n, sizeof(arr)); // ②4/8arr是数组首元素地址arr0仍是首元素的地址是指针所以大小4/8 printf(%d\n, sizeof(arr 0)); // ③1arr是数组首元素地址*arr就是首元素a1个字节所以1 // 也可以这么理解*arr -- *(arr0) -- arr[0] printf(%d\n, sizeof(*arr)); // ④1arr[1]是第二个元素b1个字节大小所以1 printf(%d\n, sizeof(arr[1])); // ⑤4/8arr是整个数组的首地址但是只要是指针就是4/8个字节 printf(%d\n, sizeof(arr)); // ⑥4/8arr是整个数组的首地址1跳过整个数组的地址但本质也是指针所以是4/8 printf(%d\n, sizeof(arr 1)); // ⑦4/8arr[0]得到第一个元素的地址1是第二个元素的地址是指针大小就是4/8 printf(%d\n, sizeof(arr[0] 1)); }5strlen字符串数组注字符串结尾自带\0所以strlen检测字符串会有确切的值解释①printf(%d\n, strlen(arr));6因为返回的长度大小不包括 \0②printf(%d\n, strlen(arr 0));6arr表示首元素地址0不变都是首元素地址所以就是从头开始计算长度仍是6③printf(%d\n, strlen(*arr));error因为strlen的参数不能是char*指针以外的类型否则结果为error而*arr是首元素是一个char类型的值所以error④printf(%d\n, strlen(arr[1]));error因为strlen的参数不能是char*指针以外的类型否则结果为error而arr[1]是第二个元素是一个char类型的值所以error⑤printf(%d\n, strlen(arr));6arr虽是整个数组的首地址但仍是从数组最开始往后计算长度仍为6⑥printf(%d\n, strlen(arr 1));随机值arr是整个数组的首地址arr 1跳过了整个数组此时往后去寻找不知道什么时候才能找到\0所以结果随机值⑦printf(%d\n, strlen(arr[0] 1));5因为arr[0] 1是第二个元素的首地址往后寻找到 \0 刚好5个元素。代码#includestdio.h int main() { char arr[] abcdef; // ①6因为返回的长度大小不包括 \0 printf(%d\n, strlen(arr)); // ②6arr表示首元素地址0不变都是首元素地址所以就是从头开始计算长度仍是6 printf(%d\n, strlen(arr 0)); // ③error因为strlen的参数不能是char*指针以外的类型否则结果为error // 而*arr是首元素是一个char类型的值所以error printf(%d\n, strlen(*arr)); // 编译报错或运行时崩溃 // ④error因为strlen的参数不能是char*指针以外的类型否则结果为error // 而arr[1]是第二个元素是一个char类型的值所以error printf(%d\n, strlen(arr[1])); // 编译报错或运行时崩溃 // ⑤6arr虽是整个数组的首地址但仍是从数组最开始往后计算长度仍为6 printf(%d\n, strlen(arr)); // ⑥随机值arr是整个数组的首地址arr 1跳过了整个数组 // 此时往后去寻找不知道什么时候才能找到\0所以结果随机值 printf(%d\n, strlen(arr 1)); // ⑦5因为arr[0] 1是第二个元素的首地址往后寻找到\0刚好5个元素 printf(%d\n, strlen(arr[0] 1)); }6sizeof赋给char*的字符串注char * pabcdef 相当于把字符串abcdef的首地址给p了(并不是把abcdef放进了p里面)并且p是首元素的地址所以p1跳过的是a而不是整个字符串类比char arr[] abcdef;arr就是首元素的地址arr1跳过了a解释①printf(%d\n, sizeof(p));4/8p是一个char*类型指针是指针大小就是4/8②printf(%d\n, sizeof(p 1));4/8p1是b的地址是指针大小就是4/8个字节③printf(%d\n, sizeof(*p))1p是首元素的地址*p 就是首元素a类型为char。大小就是1个字节④printf(%d\n, sizeof(p[0]));1p[0]就是第一个元素a所以大小为1个字节⑤printf(%d\n, sizeof(p));4/8p是char*类型p就是char**是二级指针但是只要是指针大小就是4/8⑥printf(%d\n, sizeof(p 1));4/8p是首元素的地址char*类型p就是char**此时1仍是char**是指针大小就为4/8⑦printf(%d\n, sizeof(p[0] 1));4/8 p[0]是首元素a的地址p[0] 1得到是b的地址是指针大小就是4/8代码#includestdio.h int main() { char* p abcdef; // ①4/8p是一个char*类型指针是指针大小就是4/8 printf(%d\n, sizeof(p)); // ②4/8p1是b的地址是指针大小就是4/8个字节 printf(%d\n, sizeof(p 1)); // ③1p是首元素的地址*p就是首元素a类型为char大小就是1个字节 printf(%d\n, sizeof(*p)); // ④1p[0]就是第一个元素a所以大小为1个字节 printf(%d\n, sizeof(p[0])); // ⑤4/8p是char*类型p就是char**是二级指针但是只要是指针大小就是4/8 printf(%d\n, sizeof(p)); // ⑥4/8注意p 1 是指针p本身的地址加1跳过了整个指针变量p的大小 // 但结果仍然是一个指针char**类型所以大小还是4/8 printf(%d\n, sizeof(p 1)); // ⑦4/8p[0]是首元素a的地址p[0] 1得到的是b的地址是指针大小就是4/8 printf(%d\n, sizeof(p[0] 1)); }7strlen赋给char*的字符串注char * pabcdef 相当于把字符串abcdef的首地址给p了(并不是把abcdef放进了p里面)并且p是首元素的地址所以p1跳过的是a而不是整个字符串类比char arr[] abcdef;arr就是首元素的地址arr1跳过了a解释①printf(%d\n, strlen(p));6p代表字符串的首元素地址是char*类型此时strlen从字符串最开始往后计算长度第一个元素开始寻找 \0而字符串自带\0所以结果为6(不计算\0)②printf(%d\n, strlen(p 1));5和①同理不过是从第二个元素开始寻找 \0所以为5③printf(%d\n, strlen(*p));errorp是首元素地址*p是首元素元素是astrlen的参数不能是char*以外的类型否则结果为error④printf(%d\n, strlen(p[0]));error和③同理p是首元素地址*p是首元素元素是astrlen的参数不能是char*以外的类型否则结果为error⑤printf(%d\n, strlen(p));随机值p是char*p是char**p是存储p地址的二级指针已经和原来的字符串无关了我们不知道从这个char**的二级指针开始寻找0什么时候才找到所以随机值⑥printf(%d\n, strlen(p 1));随机值和⑤同理已经和原来的字符串无关了此时char**类型二级指针即使1我们也不知道什么时候能够遇到\0所以随机值⑦printf(%d\n, strlen(p[0] 1));5p[0]是第一个元素p[0]是第首元素地址p[0]1是第二个元素地址所以strlne从第二个元素开始寻找 \0所以为58sizeof二维整形数组对于二维数组来说二维数组就是一个存放一维数组的数组其中的每个元素都是一维数组罢了对于a[3][4]来说a就是数组名既然是数组名在没有例外的情况下就代表首元素的地址按照之前的理解此时首元素为第一行数组(一维数组)整体的首地址a1或者-1会以一整行的字节大小为单位在二维数组中这样写的时候如 a[0]a[1]a[2].....此时的a[0]/a[1]/a[2]是二维数组的每一行的一维数组的数组名所以既然是数组名所以就要考虑两种特殊情况该数组名当单独放在sizeof中sizeofa[0]或者前面的时候a[0]将会满足那两个特殊条件其所指的整个数组是它所对应的那一行数组比如a[0]这个时候就代表第一行数组a[1]这个时候就代表第二行数组.......现在对其进行1-1会以一行数组作为单位来跨越。解释①printf(%d\n, sizeof(a));48a是二维数组的数组名单独处于sizeof中所以计算总字节大小3*4*4 48②printf(%d\n, sizeof(a[0][0]));4第一行第一列的元素的大小即单个元素的大小③printf(%d\n, sizeof(a[0]));16a[0]是第一个元素也就是第一行这个一维数组的数组名数组名单独放在sizeof内部了计算的是整个数组第一行的大小大小是16个字节④printf(%d\n, sizeof(a[0] 1));4/8a[0]作为第一行的数组名没有单独放在sizeo内部此时a[0]表示数组首元素的地址也就是a[0][0]的地址,所以a[0]1是第一行第二个元素的地址是指针就是4/8个字节⑤printf(%d\n, sizeof(*(a[0] 1)));4就是④的基础上加上*解引用得到了第一行第二个元素类型为int所以为4⑥printf(%d\n, sizeof(a 1));4 / 8a是数组首元素的地址也就是第一行这个一维数组整体的地址类型为 int(*)[4]此时a1 就是第二行的地址类型仍为int(*)[4]但是不管怎么复杂是指针大小就是4/8⑦printf(%d\n, sizeof(*(a 1)));16第⑥问基础上进行了*解引用对第二行的地址类型int(*)[4]进行解引用得到了第二行所以大小就是第二行的字节大小理解*(a1) -- a[1] 所以-sizeof(*(a1))-sizeof(a[1])⑧printf(%d\n, sizeof(a[0] 1));4/8a[0]是第一行这个一维数组的数组名所以a[0]就是第一行这个一维数组整体的首地址类型为int(*)[4]此时1 就是第二行的地址类型仍为int(*)[4]是指针大小就是4/8⑨printf(%d\n, sizeof(*(a[0] 1)));16第⑧问的基础是进行了*解引用括号里面得到了第二行这个一维数组所以此时大小为第二行这个一维数组的字节大小16⑩printf(%d\n, sizeof(*a));16a是二维数组的数组名此时前面有*所以不是单独处于sizeof中此时a代表首元素的地址也就是第一行这个一维数组的地址类型为int(*)[4]此时解引用得到第一行这个一维数组所以结果为4个整形的大小总和16理解“”*a -- *(a0) -- a[0]⑪printf(%d\n, sizeof(a[3]));16a[3]是第四行这个一维数组的数组名数组名单独放在sizeof中代表计算该数组的总大小所以为16虽然越界了但是正如文中最上面知识点所说其值在编译时即计算好了sizeof只会在乎你的类型然后知道了你的个数就行代码#includestdio.h int main() { // 二维数组 int a[3][4] { 0 }; // ①48a是二维数组的数组名单独处于sizeof中所以计算总字节大小3*4*4 48 printf(%d\n, sizeof(a)); // ②4第一行第一列的元素的大小即单个元素的大小 printf(%d\n, sizeof(a[0][0])); // ③16a[0]是第一个元素也就是第一行这个一维数组的数组名 // 数组名单独放在sizeof内部了计算的是整个数组第一行的大小大小是16个字节 printf(%d\n, sizeof(a[0])); // ④4/8a[0]作为第一行的数组名没有单独放在sizeof内部 // 此时a[0]表示数组首元素的地址也就是a[0][0]的地址 // 所以a[0]1是第一行第二个元素的地址是指针就是4/8个字节 printf(%d\n, sizeof(a[0] 1)); // ⑤4就是④的基础上加上*解引用得到了第一行第二个元素类型为int所以为4 printf(%d\n, sizeof(*(a[0] 1))); // ⑥4/8a是数组首元素的地址也就是第一行这个一维数组整体的地址 // 类型为 int(*)[4]此时a1就是第二行的地址类型仍为int(*)[4] // 但是不管怎么复杂是指针大小就是4/8 printf(%d\n, sizeof(a 1)); // ⑦16第⑥问基础上进行了*解引用对第二行的地址类型int(*)[4]进行解引用 // 得到了第二行所以大小就是第二行的字节大小 // 理解*(a1) -- a[1] 所以-sizeof(*(a1))-sizeof(a[1]) printf(%d\n, sizeof(*(a 1))); // ⑧4/8a[0]是第一行这个一维数组的数组名所以a[0]就是第一行这个一维数组整体的首地址 // 类型为int(*)[4]此时1就是第二行的地址类型仍为int(*)[4]是指针大小就是4/8 printf(%d\n, sizeof(a[0] 1)); // ⑨16第⑧问的基础上进行了*解引用括号里面得到了第二行这个一维数组 // 所以此时大小为第二行这个一维数组的字节大小16 printf(%d\n, sizeof(*(a[0] 1))); // ⑩16a是二维数组的数组名此时前面有*所以不是单独处于sizeof中 // 此时a代表首元素的地址也就是第一行这个一维数组的地址类型为int(*)[4] // 此时解引用得到第一行这个一维数组所以结果为4个整形的大小总和16 // 理解*a -- *(a0) -- a[0] printf(%d\n, sizeof(*a)); // ⑪16a[3]是第四行这个一维数组的数组名数组名单独放在sizeof中 // 代表计算该数组的总大小所以为16虽然越界了但是正如文中最上面知识点所说 // sizeof只会在乎你的类型在编译时即计算好了知道了你的个数就行 printf(%d\n, sizeof(a[3])); }三总结先看数组名是否触发了两种例外的情况单独放在sizeof or arr否则就是表示的数组的首元素的地址并且需要注意sizeof(*a)中的*抵消后触发单独放在sizeof中的例外情况此时赋给char*的字符串其实和字符串数组是一个道理指针p和arr 都代表的是首元素的地址1都是掉过首元素但是arr可以触发两种例外情况而p不会触发因为其不是数组名 [ 作者 ] shylyly [ 首次发布 ] 2024.3.10❌ [ 最新修改 ] 2026.5.7 [ 声明 ] 由于笔者水平有限文中难免有疏漏或不妥之处还望读者不吝赐教。