1.一维数组
大家可以先做一下,下面有解释。
#include "stdio.h" int main() { int a[] = {1,2,3,4}; printf("%d\n",sizeof(a)); printf("%d\n",sizeof(a+0)); printf("%d\n",sizeof(*a)); printf("%d\n",sizeof(a+1)); printf("%d\n",sizeof(a[1])); printf("%d\n",sizeof(&a)); printf("%d\n",sizeof(*&a)); printf("%d\n",sizeof(&a+1)); printf("%d\n",sizeof(&a[0])); printf("%d\n",sizeof(&a[0]+1)); return 0; }
1.1 sizeof( a )
我们首先知道a是数组名,因为数组名代表首元素地址,但是a是在sizeof里,代表整个数组,也就是说sizeof计算的是整个数组的大小,数组a元素有4个,数据类型是int,所以结果为4*4=16字节。
1.2 sizeof( a + 0 )
我们首先看到sizeof里面是a+0,并不是单独的a,所以这里的a代表的是首元素地址,而不是整个数组,所以a+0还是首元素地址,既然sizeof里面是地址/指针。又因为指针占的是4/8字节,所以结果为4/8字节(32位机器是4字节,64位机器是8字节)
1.3 sizeof( *a )
首先a是首元素地址,*a则是对首元素地址的解引用,取出来的是首元素,也就是a[0]是int类型,占4个字节,所以结果是4字节。
1.4 sizeof( a + 1 )
sizeof里不是单独的a,所以a是首元素地址,a+1就是第二个元素的地址,也就是&a[1],是个指针,那结果就是4/8个字节。
1.5 sizeof( a[1] )
这里a[1],很明显是第2个元素,数据类型是int,所以结果是4字节。
1.6 sizeof( &a )
&a,a代表的是首元素地址,而我们取a的地址,则是代表了取了整个数组的地址,既然是地址/指针,那就是4/8字节
1.7 sizeof( *&a )
*&a 这个表示的是我先取了整个数组的地址,再解引用,那么得到的就是整个数组,结果就是4*4=16字节。
另一种解释:*&a,*和&抵消了,剩个a,那么sizeof(a)代表的也是整个数组。
1.8 sizeof( &a + 1 )
我们要知道&是比+的优先级高的,所以&a先取了整个数组的地址,再加一,是跳过了整个数组,那也是地址,是地址就是4/8字节。
即使我们取的地址是整个数组的地址,但是也会用首元素地址来表示,只不过我们在+1之后是跳过整个数组的大小,也就是16个字节。
1.9 sizeof( &a[0] )
我们&a[0],取了首元素的地址,是地址就是4/8字节。
1.10 sizeof( &a[0] + 1 )
我们&a[0]+1,先取首元素地址再加一,得到的是&a[1],是第二个元素的地址,是地址就是4/8字节。
2.字符数组
#include "stdio.h" #include "string.h" int main() { char arr[] = {'a','b','c','d','e','f'}; printf("%d\n", sizeof(arr)); printf("%d\n", sizeof(arr+0)); printf("%d\n", sizeof(*arr)); printf("%d\n", sizeof(arr[1])); printf("%d\n", sizeof(&arr)); printf("%d\n", sizeof(&arr+1)); printf("%d\n", sizeof(&arr[0]+1)); printf("%d\n", strlen(arr)); printf("%d\n", strlen(arr+0)); printf("%d\n", strlen(*arr));// printf("%d\n", strlen(arr[1]));// printf("%d\n", strlen(&arr)); printf("%d\n", strlen(&arr+1)); printf("%d\n", strlen(&arr[0]+1)); return 0; }
2.1 sizeof( arr )
这里的arr是单独放在sizeof中的,代表的就是整个数组,所以数组一共有6个元素,是char类型,则结果为6*1=6字节。
2.2 sizeof( arr + 0 )
在这里arr不是单独放在一起的,arr代表的是首元素的地址,所以arr+0就是首元素地址,既然是地址,就是4/8个字节。
2.3 sizeof( *arr )
*arr代表的是对首元素地址的解引用,是数组的首元素,也就是arr[0],数据类型是char,结果为1字节。
2.4 sizeof( arr[1] )
arr[1]代表是arr这个数组的首元素,数据类型是char,char占的是一个字节,所以结果为1字节。
2.5 sizeof( &arr )
&arr:代表的是取出的是整个数组的地址,既然是地址,那就是4/8个字节。
2.6 sizeof( &arr + 1 )
&arr是取出整个数组的地址,加上一,依旧是个地址,我们需要明白他的本质,也就是数据类型是什么,是地址,地址就是指针,那就是4/8个字节。
2.7 sizeof( &arr[0] + 1 )
&arr [0]取出的是arr[0]的地址,也就是取数组首元素的地址,加上一,是下一个元素的地址,是地址,就是4/8字节。
回忆strlen函数
我们先回忆一下strlen函数是用来干什么的?详解可以去我上一篇文章。
strlen函数是用来测字符型数组长度的,遇到\0结束,结果是\0之前的字符个数。
我们传入的实参是一个地址,也就是指针,strlen函数是根据你所传入的地址向后去寻找\0,直到找到\0,并返回之前的字符个数。
2.8 strlen( arr )
我们实参是arr,arr只有单独出现在sizeof里才是代表整个数组,在strlen里代表首元素地址,它会从首元素地址开始往后寻找,但是由于我们这个字符数组并不包括\0,我们就不知道\0在什么位置,所以测出来的长度是随机值。(只有写成字符串形式,末尾才会有隐藏的\0。)
2.9 strlen( arr + 0 )
arr + 0 相当于 arr 也就是首元素地址,同上还是随机值。
2.10 strlen( *arr )
我们一定要明确strlen函数的实参必须是地址,*arr是首元素,arr[0]不是地址,是char类型的,这个是错误。
2.11 strlen( arr[1] )
同理,arr[1]也不是地址,数据类型是char,无法传输,也是错误。
2.12 strlen( &arr )
&arr是取到了整个数组的地址,整个数组地址和数组首元素地址是一样的,所以依旧是从数组首元素地址往后找\0,也是随机值
2.13 strlen( &arr + 1 )
&arr+1: 是在整个数组地址➕1,跳过的是整个数组字节数,也就是在这个位置向后访问,由于我们还是不知道\0的位置,依旧是随机值。
2.14 strlen( &arr[0] + 1 )
&arr[0]取到了首元素地址,&arr[0]+1是取的第二个元素地址,之后往后寻找\0,还是随机值。