c语言指针与数组关系实例解析从基础到实战

admin C语言 4


学 C 语言的时候,是不是总有人跟你说 “数组和指针差不多”?可真到用的时候,又懵了 —— 数组名到底是不是指针?为啥用指针能操作数组?用指针访问数组和用下标访问,到底哪个好?其实啊,指针和数组的关系确实密切,但也不是完全一样。今天兔子哥就从基础到实战,用实例给你讲明白,保证新手也能看懂,一起往下看吧!


一、先搞懂:数组名和指针,到底啥关系?


咱们先从最简单的一维数组说起。定义一个数组int arr[5] = {1,2,3,4,5};,这时候arr就是数组名。你试着打印一下arr&arr[0],会发现它们的值一样 —— 都是数组第一个元素的地址。
这就说明:数组名本质上是一个 “指向数组首元素的常量指针”。说它是指针,因为它存的是地址;说它是常量,因为它不能被赋值,比如arr = p;这样写会报错,而普通指针int *p;是可以被赋值的。
那为啥数组名能当指针用?其实是 C 语言的设计,为了方便操作数组。比如访问arr[2],编译器会自动转换成*(arr + 2),意思是 “从数组首地址往后移 2 个元素的位置,取这个位置的值”。
试试这段代码,感受下:
c运行
#include int main() {int arr[5] = {10,20,30,40,50};int *p = arr; // 指针p指向数组首元素,和arr一样printf("arr[2] = %d\n", arr[2]);printf("*(arr + 2) = %d\n", *(arr + 2));printf("p[2] = %d\n", p[2]);printf("*(p + 2) = %d\n", *(p + 2));return 0;}

运行后你会发现,这四种写法输出的都是 30。是不是很神奇?这就说明,数组的下标访问和指针的偏移访问,在编译器眼里是一回事。


二、用指针操作数组,到底方便在哪?


既然数组名能当指针用,为啥还要单独定义指针来操作数组呢?因为指针是变量,能移动啊!
比如想遍历数组,用指针的话,可以让指针一步步往后移,代码更简洁。看这个例子:
c运行
#include int main() {int arr[4] = {1,3,5,7};int *p = arr; // 指向首元素// 用指针遍历数组for (int i = 0; i < 4; i++) {printf("%d ", *p);p++; // 指针往后移一位,指向 next 元素}return 0;}

这段代码会输出 “1 3 5 7”,比用arr[i]遍历看起来更灵活。尤其是处理大型数组或者在函数里操作数组时,用指针能省不少事,效率也更高。
但这里要注意:指针移动的时候别 “越界”。比如数组只有 4 个元素,指针移到第 5 个位置再访问,就会读到乱码,甚至让程序崩溃。


三、二维数组和指针,是不是更复杂?


很多新手学到二维数组就头疼,其实它和指针的关系也有规律。比如int arr[2][3] = {{1,2,3}, {4,5,6}};,这时候arr是指向 “第一行数组” 的指针,它的类型是int (*)[3](指向包含 3 个 int 的数组的指针)。
可能有点绕,咱们用代码看看:
c运行
#include int main() {int arr[2][3] = {{1,2,3}, {4,5,6}};int (*p)[3] = arr; // p指向二维数组的首行printf("第一行首元素:%d\n", **p); // 输出1printf("第二行首元素:%d\n",**(p + 1)); // 输出4printf("第一行第二个元素:%d\n", *(*p + 1)); // 输出2return 0;}

这里的p是 “数组指针”,p + 1会跳过一整行(3 个元素)。*p拿到第一行的首地址,再*p + 1就是第一行第二个元素的地址,解引用就是 2。
是不是有点晕?没关系,新手可以先记住:二维数组的数组名是指向 “行” 的指针,想访问具体元素,得先定位到行,再定位到列。


四、指针和数组的区别,可别搞混了!


虽然数组名和指针很像,但它们不是一回事。咱们用个表格对比下:
区别数组名(如 arr)指针变量(如 int *p)
本质常量指针(地址不能改)变量(地址可以改)
内存存储数组元素,不单独占地址空间单独占 4 或 8 字节(存地址)
赋值不能赋值(arr = p; 报错)可以赋值(p = arr; 合法)
sizeof计算数组总字节数(如 arr [5] 是 20 字节)计算指针本身字节数(通常 8 字节)

比如sizeof(arr),如果是int arr[5],结果是 20(5×4);而sizeof(p),不管指向啥,结果都是 8(64 位系统)。这点特别重要,新手经常弄混。


五、实战案例:用指针处理数组,解决实际问题


咱们来写个程序,用指针求数组的最大值和最小值。这种场景在作业或项目里很常见。
c运行
#include // 用指针找最大最小值void findMaxMin(int *arr, int len, int *max, int *min) {*max = *arr;*min = *arr;for (int i = 1; i < len; i++) {if (*(arr + i) > *max) {*max = *(arr + i);}if (*(arr + i) < *min) {*min = *(arr + i);}}}int main() {int nums[6] = {15, 8, 23, 4, 37, 11};int max, min;findMaxMin(nums, 6, &max, &min); // 传数组名和地址printf("最大值:%d,最小值:%d\n", max, min);return 0;}

这个程序里,findMaxMin函数用指针arr接收数组,通过*(arr + i)访问每个元素,再用指针maxmin把结果传回主函数。是不是比用下标更灵活?尤其是数组很大的时候,指针操作效率更高。


兔子哥觉得,学指针和数组的关系,最好的办法就是多写代码,多打印地址和值。比如你搞不清arr + 1&arr + 1的区别,那就写段代码打印出来看看,一看就明白了。
刚开始可能觉得绕,但练多了就会发现,指针和数组结合起来用,能写出既简洁又高效的代码。记住:数组名是 “死” 的(不能动),指针是 “活” 的(能移动),分清这点,很多问题就迎刃而解了。希望今天的例子能帮你理清思路,赶紧动手试试吧!

标签: 差不多 是不是

发布评论 0条评论)

  • Refresh code

还木有评论哦,快来抢沙发吧~