相信很多小伙伴对C/C++语言中数组与指针的理解,如同阅读百年孤独一样对人名傻傻分不清,今天就来详细聊一聊令人头(tuo)疼(fa)的数组与指针。
数组名是什么?
数组名实际上就是数组首元素的地址信息,查看以下代码,
void test1(void){int nums[4] = {1, 2, 3, 4};printf("nums 的地址是: %p\n", nums);printf("&nums[0] 的地址是: %p\n", &nums[0]);return;}
运行结果如下,可以发现两者地址相同。

通过指针访问数组元素
当指针指向数组时,可以通过指针的加减运算,实现对数组元素的间接访问,查看以下代码,
void test2(void){int nums[] = {1, 2, 3, 4, 5, 6, 7};int *p = nums;for(int i = 0; i < 7; i++){printf("*(p + %d) = %d\tnums[%d] = %d\n", i, *(p + i), i, nums[i]);printf("(p + %d) = %p\t&nums[%d] = %p\n", i, (p + i), i, &nums[i]);}return ;}
运行结果如下,需要特别注意的是,p+1并不是简单的将地址加1,而是加上sizeof(datatype)的距离。

指针与数组的区别
读完上面两小节,读者会发现数组与指针似乎一模一样,其实不然。
区别一:数组一经定义,数组名便是指向数组首元素的常量指针,而指向数组的指针则可以修改。
区别二:对数组名取sizeof,得到的是整个数组占用空间的大小,对指针取sizeof为固定值,32位机为4字节,64位机为8字节。
void test3(void){int nums[] = {1, 2, 3, 4};int *p = nums;printf("sizeof nums = %ld\n", sizeof(nums));printf("sizeof p = %ld\n", sizeof(p));return ;}
运行上述代码,结果如下:

指针数组与数组指针
正确区别两者,可以从运算符优先级入手,由于下标运算符[]优先级高于取值运算符*,因此:
int *arr[4]; 指针数组int (*arr)[4]; 数组指针
指针数组本质上是数组,数组中每个元素为指针变量,请看如下代码:
void test4(void){char *arr[4] = {"百年孤独", "没有人给他写信的上校","霍乱时期的爱情", "一场事先张扬的凶杀案"};for(int i = 0; i < 4; ++i){printf("arr + %d = %s\n", i, *(arr + i));}return ;}
运行结果如下:

数组指针本质上是指针,指向一个数组,请看如下代码:
void test5(void){int nums[4] = {1, 2, 3, 4};// int (*perr)[4] = nums;int (*p)[4] = &nums;for(int i = 0; i < 4; ++i){// printf("%d\t", *(perr + i));printf("%d\t", *(*p + i));}printf("\n");return ;}
运行结果如下:

需要特别注意的是,代码上注释的两行并不能达到预期结果,这是因为perr本质上只是指向数组首元素的指针,并不是指向数组的指针,因此应该将数组名取地址再赋值给数组指针。
二维数组与指针
对于二维数组,同样可以利用指针进行访问,例如"int nums[3][4];",可进行如下转换:

查看如下代码:
void test6(void){int nums[3][4] = {{0, 1, 2, 3}, {4, 5, 6, 7},{8, 9, 10, 11}};printf("nums = %p\n", nums);printf("nums + 1 = %p\n\n", num + 1);printf("nums + 1 = %p\n", num + 1);printf("nums[1] = %p\n", nums + 1);printf("&nums[1][0] = %p\n", &nums[1][0]);printf("nums[1][0] = %d\n", nums[1][0]);printf("*(nums + 1) = %d\n\n", *(nums + 1));printf("*(nums + 2) + 3 = %p\n", *(nums + 2) + 3);printf("&nums[2][3] = %p\n", &nums[2][3]);printf("nums[2][3] = %d\n", nums[2][3]);printf("*(*(num + 2) + 3) = %d\n", *(*(nums + 2) + 3));return ;}
运行结果如下:

分析上述结果,可以发现对于二维数组 "int nums[M][N];",有:
nums + 1 = nums + sizeof(int) * N;*(nums + i) = nums[i];*(*(nums + i) + j) = nums[i][j];
后记
讲完啦,欢迎大家勘误并提出修改意见,谢谢大家。
文章转载自Code小燕儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




