前言
- sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
- &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
- 除此之外所有的数组名都表示首元素的地址。
- strlen()是求字符串长度的,关注的是字符串中的\0,计算的是\0之前出现的字符的个数
- sizeof()只关注占用内存空间的大小,不在乎内存中放的是什么
一、数组名的理解(一维数组)
数组名表示首元素地址
//一维数组
int main()
{
int a[] = {1,2,3,4}; 初始化四个元素
printf("%d\n",sizeof(a)); 16
sizeof(a),a表示整个数组,计算的是整个数组的大小,单位是字节。
printf("%d\n",sizeof(a+0)); 4/8 (32位或者64位)
a + 0 == &a[0]+0
sizeof(a+0),数组名a+0等于首元素+0,结果就是 4/8
printf("%d\n",sizeof(*a)); 4
sizeof(*a) *a中的a是数组首元素的地址,*a就是对首元素的地址解引用,找到的就是首元素
printf("%d\n",sizeof(a+1)); 4/8
sizeof(a+1) 首元素 + 1
printf("%d\n",sizeof(a[1])); 4
sizeof(a[1]) 计算的是下标位1的大小
printf("%d\n",sizeof(&a)); 4/8
sizeof(&a) &a取出的数组的地址,数组的地址,也就是个地址,数组的地址就是4/8字节,主要是地址就是4/8
printf("%d\n",sizeof(*&a)); 16
sizeof(*&a) *和&抵消剩下个a
数组的解引用就是访问整个数组
&a拿到的是数组名的地址,类型是int(*)[4],是一种数组指针
数组指针解引用找到的是 *&a ----> a
printf("%d\n",sizeof(&a+1)); 4/8
&a + 1 是从数组a的地址向后跳过一个(4个整形元素的)数组的大小
&a + 1 还是地址,是地址就是4/8字节
printf("%d\n",sizeof(&a[0])); 4
就是首元素元素的地址
计算的是地址的大小
printf("%d\n",sizeof(&a[0]+1)); 4/8
计算的是第二个元素的地址
return 0;
}
二、数组名的理解(字符数组)
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = {'a','b','c','d','e','f'}; 7个元素(\0)
printf("%d\n", sizeof(arr)); 6
一个数组1个字节不算\0
printf("%d\n", sizeof(arr+0)); 4/8
sizeof(arr+0) 是数组首元素的地址 是地址在这就是4/8
printf("%d\n", sizeof(*arr)); 1
8arr就是数组首元素,大小是1字节
*arr == arr[0]
*(arr+0) == arr[0]
arr+0就是首元素大小
printf("%d\n", sizeof(arr[1])); 1
printf("%d\n", sizeof(&arr));4/8
&arr是数组的地址,是地址就是4/8
printf("%d\n", sizeof(&arr+1)); 4/8
&arr+1跳过整个数组,指向下个地址,是地址就是4/8
printf("%d\n", sizeof(&arr[0]+1)); 4/8
&arr[0] + 1 是第二个元素的地址
是地址就是4/8个字节
strlen
printf("%d\n", strlen(arr)); 随机值
arr首元素strlen会一直向后跑知道找到\0
一直往后寻找知道找到\0
printf("%d\n", strlen(arr+0)); 还是随机值
arr+0 还是首元素地址
printf("%d\n", strlen(*arr)); strlen('a');--->strlen(97);野指针
strlrn要传过去地址
不传地址会报错
printf("%d\n", strlen(arr[1])); strlen('b');--->strlen(98);野指针
报错
printf("%d\n", strlen(&arr)); 随机值
printf("%d\n", strlen(&arr+1)); 随机值-6
因为跳过一个数组进入下一个数组
printf("%d\n", strlen(&arr[0]+1)); 随机值-1
从下标0加1开始向后找\0.所以-1
return 0
}
三、数组名的理解(字符串数组)
int main()
{
char arr[] = "abcdef"; 7
printf("%d\n", sizeof(arr)); 7
printf("%d\n", sizeof(arr+0)); 4/8
arr+0就是首元素地址 只要是地址就是4/8
printf("%d\n", sizeof(*arr)); 1
*arr arr表示首元素地址 a的解引用得到a
a就是1一个字节
printf("%d\n", sizeof(arr[1])); 1
计算下标为1的大小
printf("%d\n", sizeof(&arr));4/8
是地址就是4/8
printf("%d\n", sizeof(&arr+1)); 4/8
跳过整个数组 指向下一个数组
printf("%d\n", sizeof(&arr[0]+1)); 4/8
这里取的是b的地址 是地址那就是4/8
strlen
printf("%d\n", strlen(arr)); 6
printf("%d\n", strlen(arr+0)); 6
arr+0首元素+0还是首元素
printf("%d\n", strlen(*arr)); 报错
把首元素地址解引用
strlen只能传地址
printf("%d\n", strlen(arr[1])); 报错
printf("%d\n", strlen(&arr)); 6
printf("%d\n", strlen(&arr+1)); 随机
printf("%d\n", strlen(&arr[0]+1)); 5
首元素+1开始计算
return 0;
}
四、数组名的理解(字符串指针)
int main()
{
char *p = "abcdef";
p有自己的空间
存放的是abcdef的地址
printf("%d\n", sizeof(p)); 4/8
p是个指针变量,用sizeof来算那就是4/8字节
printf("%d\n", sizeof(p+1)); 4/8
p的地址+1 还是地址,是地址就是4/8字节
printf("%d\n", sizeof(*p)); 1
printf("%d\n", sizeof(p[0])); 1
p[0]-->*(p+0)p本来就是指向首元素的+0等于没加==*p
对一级指针取地址运算就是就相当于二级指针
printf("%d\n", sizeof(&p)); 4/8
取出的是字符指针的地址 还是地址,只要是地址就是4/8
printf("%d\n", sizeof(&p+1)); 4/8
地址+1还是地址
&+1跳过本地址,指向下一个地址
printf("%d\n", sizeof(&p[0]+1));4/8
&p[0]+1 指向b的地址 地址就是4/8
strlen()
printf("%d\n", strlen(p)); 6
p里面放的是a的地址,传给strlen后计算到\0就停止
printf("%d\n", strlen(p+1)); 5
p+1 首地址+1指向第二个字符b 开始计算就是5
printf("%d\n", strlen(*p)); 报错
p存放a 将p解引用就是得到a,然后就报错
printf("%d\n", strlen(p[0])); 报错
printf("%d\n", strlen(&p)); 随机值
&p与abcdef的空间无关什么时候找到\0不知道
printf("%d\n", strlen(&p+1)); 随机值
printf("%d\n", strlen(&p[0]+1)); 5
&p[0]已经指向a, +1后指向b,然后计算到\0停止
return 0;
}
五、二维数组
在内存中是一段连续的空间
int main()
{
//二维数组
int a[3][4] = {0};
&a + 1 跳过整个二维数组
printf("%d\n",sizeof(a)); 3x4x4= 48
printf("%d\n",sizeof(a[0][0])); 4
第一行第一列
printf("%d\n",sizeof(a[0])); 4x4 = 16
a[0] = 是第一行这个一维数组的数组名,单独放在sizeof内部,a[0]表示第一个整个这个一维数组
sizeof(a[]0)计算的就是第一行的大小
printf("%d\n",sizeof(a[0]+1)); 4/8
a[0]并没有单独放在sizeof内部,也没有取地址,a[0]就表示首元素的地址
就是第一行这个一维数组的第一个元素的地址,
a[0]+1计算第一行第二个元素的地址
printf("%d\n",sizeof(*(a[0]+1))); 4
a[0]+1是第一行第二个元素
*(a[0]+1)就是第一行第二个元素
printf("%d\n",sizeof(a+1)); 16
a虽然是二维数组的地址,但是并没有单独放在sizeof内部,也没取地址
a表示首元素的地址,二维数组的首元素是它的第一行,a就是第一行的地址
a+1就是跳过第一行,表示第二行的地址
printf("%d\n",sizeof(*(a+1))); 16
对第二行的地址解引用 就拿到第二行了
计算的是第二行
*(a+1) --> a[1]
sizeof(*(a+1))--> sizeof(a[1])
printf("%d\n",sizeof(&a[0]+1)); 16
&a[0]-->a[0]在二维数组中表示第一行,取出第一行地址后进行+1
拿到第二行的地址
printf("%d\n",sizeof(*(&a[0]+1))); 4/8
对第二行解引用拿到第二行的地址
但只是拿到了地址
printf("%d\n",sizeof(*a)); 16
a首元素地址
第一行解引用拿到第一行
printf("%d\n",sizeof(a[3])); 16
表示第四行的地址sizeof(a[3])进行计算不进行访问
return 0;
}