指针深度解刨《三》(数组的认知)
今天我们主要讲下数组的认知。
今天大家也要心情愉悦哦。
目录
数组中的内存分配
那么如果是数组形式创建的变量集合会是怎么样呢?
&a[0] 和 &a区别
sizeof的使用
了解下指针+1的大小
常规指针
如果发生强制转化呢?
那么如果是二级以上的指针呢?
数组元素+1的结果
为什么会首元素地址和整个元素的地址相同呢?
数组名的左值和右值
首先数组名可以做右值,看个例子:
那么变量名可以做左值吗?
下期预告:
数组中的内存分配
数组的内存分配和指针一样吗?也是由低地址向高地址递增吗?
int a = 10;int b = 20;int c = 30;printf("&a = %p\n", &a);printf("&b = %p\n", &b);printf("&c = %p\n", &c);
这里的每个地址都是从高到低递减的,本质是因为a先入栈,先创建,并且由于栈区的存储结构导致的,这点我们后续讲栈帧详细说,下面就简单的图供大家理解下:(先使用栈区的高地址)
那么如果是数组形式创建的变量集合会是怎么样呢?
下面以char类型数组举例:
#define NUM 10int main(){char arr[NUM] = { 0 };for (int i = 0; i < 10; i++){printf("arr[%d] = %p\n", i, &arr[i]);}return 0;}
我们可以看出数组的地址是在递增的,和上面的创建一个个变量的形式不同。因为数组的空间是线性连续且递增,开辟空间时是整体开辟开辟空间和整体释放,并且开辟时,是首元素作为最低的地址。
&a[0] 和 &a区别
sizeof的使用
首先我们先补充下sizeof剩下的一些知识:
sizeof(a):是sizeof中单独放数组名,表示整个数组的大小。
sizeof(&a):这时取出来的是整个数组的地址。
sizeof(&a[0]):取出的是数组首元素的地址。
了解下指针+1的大小
首先为什么要讲这个呢?因为我们后续要讲对 数组的地址加1 的影响。
常规指针
char *a = NULL;short *b = NULL;int *c = NULL;double *d = NULL;printf("%d\n",a);printf("%d\n\n",a+1);printf("%d\n", b);printf("%d\n\n", b + 1);printf("%d\n", c);printf("%d\n\n", c + 1);printf("%d\n", d);printf("%d\n\n", d + 1);
这是结果和相对指针加一后的值,这是跟指针类型有关的。对指针加一,本质是加上所指向类型的大小。(不考虑强制类型转化)。
如果发生强制转化呢?
如果有强制转化,就看强制转化的类型。
那么如果是二级以上的指针呢?
int main(){double ******d = NULL;printf("%d\n", d);printf("%d\n\n",d + 1);return 0;}
多级指针+1后只会向后移动4个字节,因为二级和二级以上的指针变量,存放都是地址,地址在32位下都是4个字节,所以只会向后移动4个字节。
数组元素+1的结果
聊过上述指针的步长的问题后,再说数组步长的问题就好理解点。
看个例子:
char a[NUM] = { 0 };printf("%p\n", &a[0]);printf("%p\n", &a[0]+1);printf("%p\n", &a);printf("%p\n", &a+1);
首先我们能看到,数组的首元素地址和整个数组地址一样。首元素地址+1,是向后+1个首元素类型的大小,整个数组的地址+1,是向后移动整个数组大小。本质上是类型不同,因为首元素的类型和整个数组的类型不一样。
为什么会首元素地址和整个元素的地址相同呢?
首先要知道,所有的取地址操作,不管是整形,浮点,还是结构体,包括数组,都是取出众多地址值中最小的。那么数组首元素的地址是地址最低的,那么取出首元素的地址,和整个元素的地址就相同了,只不过它们的类型不同,+1之后的结果不同。
数组名的左值和右值
首先数组名可以做右值,看个例子:
char arr[NUM] = { 0 };char *p = arr;printf("%p\n", p);printf("%p\n", arr);return 0;
这里看出来变量名做右值,是把首元素地址赋给变量p了,这是可以的(不能用&arr,类型不同)
那么变量名可以做左值吗?
int arr[NUM] = { 0 };arr = { 1, 2, 3, 4, 5 };
j
首先,变量是要有空间的,数组也不例外,也有空间,但是数组名不能做左值,因为在C语言中,数组不可以整体赋值,只能被整体初始化。所以,不能赋值,也就不能做左值了。
下期预告:
下期我们要说指针和数组的”亲密“关系
下期更精彩哦~!~!~!