数组指针和指针数组的区别
从名字上来看数组指针
和指针数组
很容易混淆, 但是他们的区别是很大的
- 数组指针: 数组指针是指向一个数组的指针, 本身只占用对应的类型的空间, 如 int类型, 则只占用4个字节
- 指针数组: 指针数组是由多个指针构成的一个数组,数组中的每个元素都是一个指针,占用的空间 = 类型*长度
定义:
// 由于[]的优先级比*要高, 所以定义数组指针的时候一定要加小括号
int *pa[5]; // 指针数组, 占用20个字节
int (*pa1)[5]; // 数组指针, 占用4个字节
使用数组名遍历数组
#include <stdio.h>
int main()
{
int arr[4][5] = {
{1, 2, 3, 4, 5},
{11, 12, 13, 14, 15},
{21, 22, 23, 24, 25},
{31, 32, 33, 34, 35},
};
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {
printf("%4d", *(*(arr+i))+j); // 对数组名进行两层解引用
}
printf("\n");
}
return 0;
}
解析
在c语言中,数组名存储的是数组第一个元素的地址, 可以得出arr = &arr[0]
, 所以, 数组名其实也相当于一个指针
arr+1
指向的其实是 arr[1]
, 而arr[1]
里存储的是指向 arr[1][0]
的地址,所以, 对arr+1
进行解引用,得到的是arr[1][0]
的地址,而不是值, 所以*(arr+1) = &arr[1][0]
;
如果将*(arr+1)
再加一, 那么提到的将会是arr[1][1]
的地址, 故(*(arr+1)+1) = &arr[1][1]
,
如果再一次对其进行解引用, 那么得到的才是真正的值
*(*(arr+1)+1) = arr[1][1]
;
下面我们用代码试验一下
printf("arr指向的地址: %p\n", arr);
printf("arr[0]的地址: %p\n", &arr[0]);
printf("\n");
printf("arr+1的地址: %p\n", arr+1);
printf("arr[1]的地址: %p\n", arr[1]);
printf("\n");
printf("arr[1][0的地址: %p\n", &arr[1][0]);
printf("*(arr+1)的地址: %p\n", *(arr+1));
printf("\n");
printf("*(*(arr+1))的值为: %d\n", *(*(arr+1)));
printf("*(*(arr+1)+1)的值为: %d\n", *(*(arr+1)+1));
结果为
arr指向的地址: 0x7ffeebacaaa0
arr[0]的地址: 0x7ffeebacaaa0
arr+1的地址: 0x7ffeebacaab4
arr[1]的地址: 0x7ffeebacaab4
arr[1][0的地址: 0x7ffeebacaab4
*(arr+1)的地址: 0x7ffeebacaab4
*(*(arr+1))的值为: 11
*(*(arr+1)+1)的值为: 12
可以看出, &arr[1] - &arr[0] = 0X14
; 16进制的14等于10进制的20, 一个int占用4个字节, 20正好是5个元素, 也就是arr+1的跨度为一行
使用数组指针
#include <stdio.h>
int main()
{
int arr[4][5] = {
{1, 2, 3, 4, 5},
{11, 12, 13, 14, 15},
{21, 22, 23, 24, 25},
{31, 32, 33, 34, 35},
};
// 定义数组指针,指向arr数组, 占用4个字节
// 此处的[5], 5代表 如果p+1, 那么将会前进5*4 = 20个字节, 正好处于数组的下一行
// 因为一个int占用4个字节, 所以是5*4, 如果对象为 double格式, 占用的将会是8个字节, 跟随数据类型来变化
int (*pa)[5] = arr;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {
printf("%4d", *(*(pa+i))+j);
}
printf("\n");
}
return 0;
}
打印结果
shantong@mac ~/c-project gcc array_pointer.c && ./a.out
1 1 1 1 1
11 11 11 11 11
21 21 21 21 21
31 31 31 31 31
此处用法和上面的数组名一样, 其中的原理也是一样的, 但是可以通过指针来间接达成目的