C语言中的数组和指针

先看段代码

1	int arr[] = {344,243,55,6,10};
2	for (int i = 0; i < 5; i++) 
3      printf("%p\n", &arr[i]);

数组arr的每个元素的地址,依次被打印,运行结果如下

10x7fff5c45b590
20x7fff5c45b594
30x7fff5c45b598
40x7fff5c45b59c
50x7fff5c45b5a0

每个地址相差4,正好是一个int型整数占的字节数。

问题来了,是不是每个元素的地址,正好相差元素数据类型所占的字节数呢?

答案:是的。

再来看段代码验证一下

 1	char arr[] = "abcd";
 2	for (int i = 0; i < 4; i++) 
 3		printf("%p\n", &arr[i]);
 4
 5	for (int i = 0; i < 14; i++)
 6		printf("-");
 7
 8	printf("\n");
 9
10	double arr2[] = {10.000, 13.2, 15.6, 123.678};
11	for (int i = 0; i < 4; i++) 
12		printf("%p\n", &arr2[i]);

运行结果

 10x7fff5c2c8577
 20x7fff5c2c8578
 30x7fff5c2c8579
 40x7fff5c2c857a
 50x7fff5c2c857b
 6--------------
 70x7fff5c2c8580
 80x7fff5c2c8588
 90x7fff5c2c8590
100x7fff5c2c8598
110x7fff5c2c85a0

字符串可被看作字符数组,每个字符占1个字节,地址相差1。

双精度型数组,每个元素占8个字节,地址相差8。

可见,上面的结论是对的。

地址到底指什么呢?

依据这里的描述

The address of a variable is the address of its first byte of storage that it occupies

每个变量可能会占若干字节,变量地址指的是它所占的第一个字节的地址。

所以,当我们打印数组每个元素的地址时,实际上是在打印每个元素所占的第一个字节的地址。

说到地址,自然想到指针,于是我们想知道

究竟啥是指针?

通常所说的指针是指指针变量,这种变量的值是十六进制的地址,而该地址可能属于另一个变量。所以,通过指针变量可以取到它所存的地址所属的变量(或许没有变量)的值。举个例子

1	int a = 100;
2	int *p;
3	p = &a;
4
5	printf("%p\n", p);
6	printf("%d\n", *p);

p是指针变量,它的值是变量a的地址,通过*p获取到a的值。运行结果

10x7fff5065d5a8
2100

再回到数组,做个实验

1	int arr[] = {344,243,55,6,10};
2	printf("%p\n", arr);
3	printf("%p\n", &arr[0]);

运行结果

10x7fff5d0d0590
20x7fff5d0d0590

可见,数组名arr本身可被看作一个指针变量,它保存的正是第一个元素的地址。在c语言中,arr+1表示指针指向下一个元素的地址,所以,下面的等式是成立的

1arr+n = &(arr[n])
2*(arr+n) = arr[n]

综上所描述,可得结论

数组名可看作指向数组第一个元素的指针,指针加n,则指向数组第n个元素