宗旨
- sizeof(数组名),这里的数组名表示整个数组,计算整个数组的大小。
- &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
- 除此之外所有的数组名都表示首元素地址
-
举例
-
一维数组
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));
- sizeof(a):即第一种情况,是整个数组的大小,4个int型,一个int大小为4byte,共16字节。
-
sizeof(a+0):此处注意要与第一种情况区别只能表示首元素地址,既然是地址则可能为4/8字节(32位下是4字节,64位下是8字节)。
- sizeof(*a):表示首元素大小,为4字节。
- sizeof(a+1):与第二种情况相似表示第二个元素的地址,大小为4/8字节。
- sizeof(a[1]):与第三种情况相似,表示数组的第二个元素,大小为4。
- sizeof(&a):表示整个数组的地址,也是地址,大小为4/8字节。
- sizeof(*&a):可以理解为&和*相互抵消,与第一种情况相同,即整个数组的大小,或理解为&a是int(*)[4]类型的数组指针,如果解引用,访问的就是4个int的数组,大小是16个字节。
- sizeof(&a+1):表示跨过整个数后的地址,是地址就是4/6.
- sizeof(&a[0]):表示取出第一的元素的地址。
总结:
- sizeof只关注占空间大小,单位是字节
- sizeof不关注类型
- sizeof是操作符
字符数组
sizeof
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));
- sizeof(arr):arr作为数组名单独放在sizeof中,计算整个数组的大小,为6字节。
- sizeof(arr+0):arr就是首元素地址,地址大小就是4/8.
- sizeof(*arr):表示首元素大小,为1字节。
- sizeof(arr[1]):表示第二个元素,大小为1字节。
- sizeof(&arr):取出了数组的地址,地址就是4/8字节。
- sizeof(&arr+1):跳过了整个数组,还是地址,大小为4/8.
- sizeof(&arr[0]+1):表示第二个元素的地址,地址就是4/8.
strlen
char arr[] = {'a','b','c','d','e','f'};
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));
- strlen(arr):因为末尾没有\0,所以是随机值。
- strlen(arr+0):与上一个相同,随机值。
- sizeof(*arr):表示第一个元素,大小为1字节。
- sizeof(arr[1]):表示第二个元素,大小为1字节。
- sizeof(&arr):表示整个数组的地址,是地址大小就是4/8.
- sizeof(&arr+1):表示跨过整个数组位置的地址,大小为4/8.
- sizeof(&arr[0]+1):表示第二个元素的地址,大小为4/8.
sizeof
char *p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p+1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p+1));
printf("%d\n", sizeof(&p[0]+1));
- sizeof(p):计算指针变量的大小,4/8字节。
- sizeof(p+1):下一个char位置的地址,大小为4/8.
- sizeof(*p):访问的是一个字节。
- sizeof(p[0]):p[0]<==>*(p+0),一个字节。
- sizeof(&p):二级指针也是指针,4/8字节。
- sizeof(&p+1):在内存中跳到p指针后一个地址,已经与数组无关,但也是地址大小为4/8.
- sizeof(&p[0]+1):p[0]是‘a’,&后为此处地址,加1是下一个元素‘b’的地址,是地址就是4/8.
strlen
char* p = "abcdef";
printf("%d\n", strlen(p));
printf("%d\n", strlen(p+1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p+1));
printf("%d\n", strlen(&p[0]+1));
1.strlen(p):p指向字符串首地址,strlen会从a开始一直读到'\0',即字符串的长度,为6.
2.p+1会指向b,从此处开始向后一共5个字符,长度为5
3.*p表示字符a对应的ASCII码值,放入strlen表示从0X00000061地址处一直读到\0,但没有访问权
会进行如下报错。
4.p[0]==*(p+0),所以与3结果相同。
5.此处易错,p仅仅是指向字符串,&p之后将与数组无关,strlen会一直从p自己的位置一直往后读到'\0',此处结果为随机值。
6.与5相似,只不过结果会比5的结果小1.
7.先进行解引用在进行取地址,表示‘a'的地址,+1即从b开始向后,长度为5.
二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));//1
printf("%d\n",sizeof(a[0][0]));//2
printf("%d\n",sizeof(a[0]));//3
printf("%d\n",sizeof(a[0]+1));//4
printf("%d\n",sizeof(*(a[0]+1)));//5
printf("%d\n",sizeof(a+1));//6
printf("%d\n",sizeof(*(a+1)));//7
printf("%d\n",sizeof(&a[0]+1));//8
printf("%d\n",sizeof(*(&a[0]+1)));//9
printf("%d\n",sizeof(*a));//10
printf("%d\n",sizeof(a[3]));//11
1.数组名单独放在sizeo内部表示整个数组的大小,3*4*4=48byte。
2.表示第第一行第一个元素的大小为4.
3.a[0]表示第一行的数组名,作为数组名单独放在sizeof内部表示整个数组的大小=16byte。
4.a[0]作为数组名没有单独放在sizeof内部,就是首元素地址,a[0]+1就是第二行地址,是地址就是4/8.
5.表示第一行第二个元素的大小=4.
6.a没有单独放在sizeof内部,a就是首元素地址,即第一行的地址,a+1是第二行的地址,是类型为int(*)[4]的指针数组,是地址就是4/8.
7.*(a+1)就是第二行的数组名,相当于a[1],sizeof( a[1] )大小为16byte。
8.a[0]是第一行,&a[0]是第一行的地址,&a[0]+1是第二行的地址,地址就是4/8.
9.第二行的地址解引用就是第二行 也就是a[1],大小是16byte.
10.a是二维数组数组名,没有&,没有单独在sizeof内部,a表示首元素地址,*a是二维数组的首元素,也就是第一行,=16byte。
11.感觉a[3]越界了,但它依然表示一个大小为int[4]的元素,=16byte。