要领
1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小
2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址。
目录
1、一维数组
指出下列具体含义
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
这里a是代表整个数组,计算数组总大小,int类型,所以是16个字节
printf("%d\n",sizeof(a+0));
a并非单独放在sizeof内部,也没有&,所以数组名a就是数组首元素的地址,这里a+0是表示首元素地址,地址就是4/8个字节(X86是4个字节,X64是8个字节)
printf("%d\n",sizeof(*a));
a是首元素的地址,*a就是首元素,sizeof(*a)就算的就是首元素的大小 —— 4
printf("%d\n",sizeof(a+1));
a是首元素的地址,a+1是第二个元素的地址,sizeof(a+1)计算的是指针的大小—— 4/8
printf("%d\n",sizeof(a[1]));
a[1] 相当于 *(a+1) ,就是数组的第二个元素,sizeof(a[1])的大小 -—— 4个字节
printf("%d\n",sizeof(&a));
正是特例之一,&a取出的数组的地址,数组的地址,也是地址,sizeof(&a)就是 4/8 个字节
printf("%d\n",sizeof(*&a));
*解引用与&取地址相互抵消,就是访问整个数组, sizeof(*&a) ==> sizeof(a) =16
只能*&抵消不能&*抵消
printf("%d\n",sizeof(&a+1));
&a数组的地址,&a+1跳过整个数组,&a+1还是地址,是 4/8 个字节
printf("%d\n",sizeof(&a[0]));
a[0]是数组的第一个元素,&a[0]是第一个元素的地址,是 4/8 个字节
printf("%d\n",sizeof(&a[0]+1));
a[0]是数组的第一个元素,&a[0]+1是第二个元素的地址,是 4/8 个字节
2、二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));
a是二维数组的数组名,数组名单独放在sizeof内部,计算的是数组的总大小,单位是字节——48
printf("%d\n",sizeof(a[0][0]));
a[0][0]是一个整型元素,大小是4个字节, a[0][0] ==> *(*(a+0)+0)
printf("%d\n",sizeof(a[0]));
这是代表第零行,这一行有四列,所以是16字节
printf("%d\n",sizeof(a[0]+1));
a[0]虽然是第一行的数组名,但是并非单独放在sizeof内部
a[0]作为第一行的数组名并非表示整个第一行这个数组,a[0]就是第一行首元素的地址
a[0]--> &a[0][0]
a[0]+1,跳过一个int,是a[0][1]的地址 4/8字节
printf("%d\n",sizeof(*(a[0]+1)));
*(*(a+0)+1)==> a[0][1],第一行的第二个元素,4个字节
printf("%d\n",sizeof(a+1));
a是二维数组的数组名,没单独放在sizeof内部,也没有&,所以a就是数组首元素的地址
二维数组,我们把它想象成一维数组,它的第一个元素就是二维数组的第一行
a就是第一行的地址,a+1 是第二行的地址,是地址,大小就是 4/8 个字节
eg: a ==> &a[0] a+1 ==> &a[1] a+2 ==> &a[2]
> printf("%d\n",sizeof(*(a+1)));
a+1就是第二行的地址,*(a + 1)找到的就是第二行, sizeof(*(a + 1))计算的就是第二行的大小16个字节
printf("%d\n",sizeof(&a[0]+1));
&a[0]这是第一行地址,&a[0]+1就是第二行地址,是地址就是4/8字节
> printf("%d\n",sizeof (*(&a[0]+1)));
由上面一个知,里面的是第二行的地址,*(&a[0]+1))则是找到第二行,sizeof(*(a + 1))计算的就是第二行的大小16个字节
printf("%d\n",sizeof(*a));
a是二维数组的数组名,没单独放在sizeof内部,也没有&,所以a就是数组首元素的地址,就是第一行的地址 - &a[0] ==》 &*(a+0)
*a - > *(a+0) - > a[0]
printf("%d\n",sizeof(a[3]));
任何一个表达式有2个属性
3+5
值属性:8
类型属性:int
a[3]是二维数组的第4行,虽然没有第四行,但是类型能够确定,大小就是确定的。大小就是一行的大小,单位是字节 - 16, 能够分析出 a[3]的类型是:int [4]
3、字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));
arr代表整个数组,arr是数组名,并且是单独放在sizeof内部,计算的是数组总大小,单位是字节 - 类型是char 所以共6个字节
printf("%d\n", sizeof(arr+0));
arr是数组名,并非单独放在sizeof内部,这里代表首元素地址,地址大小为4/8字节
printf("%d\n", sizeof(*arr));
arr是首元素的地址,*arr就是首元素,sizeof计算的是首元素的大小,是1字节
printf("%d\n", sizeof(arr[1]));
arr[1]表示第二个元素,所以字节为1
printf("%d\n", sizeof(&arr));
表示整个数组地址,地址就是4/8字节
printf("%d\n", sizeof(&arr+1));
&arr是数组的地址,&arr+1跳过整个数组,指向'f'的后边,&arr+1的本质还是地址,是地址就是4/8
printf("%d\n", sizeof(&arr[0]+1));
&arr[0]是‘a’的地址,&arr[0]+1是'b'的地址,是地址就是4/8字节
printf("%d\n", strlen(arr));
取的是随机值,arr是数组名,但是没有放在sizeof内部,也没&,arr就是首元素的地址
strlen得到arr后,从arr数组首元素的地方开始计算字符串的长度,直到直到\0(strlen是要访问到\0才会停止计数)但是arr数组中没有\0,arr内存的后边是否有\0,在什么位置是不确定的,所以\0之前出现了多少个字符是随机的。
printf("%d\n", strlen(arr+0));
arr代表首元素地址,arr+0表示第一个元素的地址,切不可以为这里地址就是4/8字节,这里是strlen不是sizeof,要去访问到\0才停止
printf("%d\n", strlen(*arr));
arr是数组首元素的地址,*arr 是首元素 - ‘a’ - 97,strlen就把‘a’的ASCII码值 97 当成了地址,err 会非法访问内存
printf("%d\n", strlen(arr[1]));
arr[1] - 'b' - 98 - err
printf("%d\n", strlen(&arr));
随机值,&arr是数组的地址,数组的地址也是指向数组起始位置
printf("%d\n", strlen(&arr+1));
随机值
printf("%d\n", strlen(&arr[0]+1));
随机值
4、字符串数组
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
arr单独放在sizeof里代表整个数组,7个字节(别忘了还有\0)
printf("%d\n", sizeof(arr+0));
arr不是在sizeof里单独存在所以是首元素地址,这里表示'a'的地址,4/8字节
printf("%d\n", sizeof(*arr));
arr不是在sizeof里单独存在所以是首元素地址,取星找到首地址的元素’a‘,所以1字节
printf("%d\n", sizeof(arr[1]));
*(a+1)表示找到第二个元素'b',所以是一字节
printf("%d\n", sizeof(&arr));
&a表示得到整个数组的地址,也是地址,4/8字节
printf("%d\n", sizeof(&arr+1));
得到整个数组地址,&arr+1跳过这个数组,是地址所以是4/8字节
printf("%d\n", sizeof(&arr[0]+1));
表示第二个元素地址,是地址就是4/8字节
printf("%d\n", strlen(arr));
这可不是随机值,有\0,所以是6字节
printf("%d\n", strlen(arr+0));
表示首地址元素,所以从首元素开始访问,6个字节
printf("%d\n", strlen(*arr));
arr是数组首元素的地址,*arr 是首元素 - ‘a’ - 97,strlen就把‘a’的ASCII码值 97 当成了地址,err 会非法访问内存
printf("%d\n", strlen(arr[1]));
arr[1] ==> *(arr+1) 所以找到第二个元素的值,err
printf("%d\n", strlen(&arr));
&arr表示整个数组的地址,数组的地址也是指向数组起始位置,所以是6字节
printf("%d\n", strlen(&arr+1));
&arr表示整个数组的地址,&arr+1表示跳过整个数组,所以什么时候会遇见\0无从而知,所以是随机值
printf("%d\n", strlen(&arr[0]+1));
从第二个元素开始访问,到\0结束,所以是5个字节
5、指针数组
char *p = "abcdef";
printf("%d\n", sizeof(p));
p是指针变量,用来存放地址,地址在X86下是4个字节,在X64下是8个字节 4/8
printf("%d\n", sizeof(p+1));
由第一个知这也是个地址,p+1就是第二个元素的地址,是地址就是4/8字节
printf("%d\n", sizeof(*p));
是char*类型,解引用也只能得到一个字节
printf("%d\n", sizeof(p[0]));
p[0] ==> *(p+0) 代表找到第一个元素,char类型下一个元素是1个字节
printf("%d\n", sizeof(&p));
取p变量的地址,是地址,就是4/8字节
printf("%d\n", sizeof(&p+1));
&p+1地址如下,再怎么说也是地址,所以是4/8字节
printf("%d\n", sizeof(&p[0]+1));
表示第二个元素的地址,地址大小为4/8字节
printf("%d\n", strlen(p));
单独放置,没有sizeof,所以代表的是首元素地址,所以是6字节
printf("%d\n", strlen(p+1));
表示第二个元素地址开始访问,所以是5字节
printf("%d\n", strlen(*p));
p是数组第一个元素地址,解引用后就找到了里面的'a',所以得到了97,非法访问err
printf("%d\n", strlen(p[0]));
p[0] ==> *(p+0) 所以其实就是*p,还是err
printf("%d\n", strlen(&p));
变量P是指针变量,取指针变量的地址,这个地址里面不知道什么时候会出现\0,所以是随机值
printf("%d\n", strlen(&p+1));
同上也是随机值,&p+1也不知道什么时候会出现\0
printf("%d\n", strlen(&p[0]+1));
从第二个元素开始访问,所以是5字节