创业和打工的想法有什么不同 数组和指针的区别

在《C语言揭秘:各种数据类型》中已经介绍了指针和数组,但在实际编码中指针和数组容易被错误使用,本文就有必要从不同场景分析它们互通性和独特性 。
访问指针所指变量
C语言中,指针是指向其他变量的变量 。比如:
int n = 10;int * pn;int main(){ pn = &n;}
pn就是一个指针变量,它指向变量n,pn的值就是n的地址,这个我们已经知道了 。
我们访问n,可以用:
int n1 = 0xbabebeaf;int n2 = 0xdeaddeaf;int *pn1;int *pn2;int main(){pn1 = &n1;pn2 = &n2;*pn1 = 5;// 解引用方式pn2[0] = 8; // 数组下标方式}
得到:
【创业和打工的想法有什么不同 数组和指针的区别】

创业和打工的想法有什么不同 数组和指针的区别

文章插图
11行是正常的解引用方式,好理解 。
重点注意第12行,采用了数组下标的方式给n2赋值,可以看到与上图中0xa0000004中的值0x8匹配,说明赋值成功 。即这种情况下,解引用和数组下标方式通用 。
访问数组元素
int arr1[2] = {1,2};int arr2[2] = {3,4};int main(){*arr1 = 5;arr2[0] = 8;}
得到结果:
创业和打工的想法有什么不同 数组和指针的区别

文章插图
可以看到6、7行都可以成功给数组中第一个元素赋值 。因此2种方式通用 。
指针的地址
指针作为一个变量也可以取其地址,那就是二重指针,比如:
int n1 = 0xbabebeaf;int *pn1;int **ppn1; // 二重指针int main(){n1 = 5;// n1的值为5pn1 = &n1;// pn1的地址为n1的地址0xa0000000ppn1 = &pn1; //取指针变量pn1的地址赋给ppn1,即ppn1的值为0xa0000008}
得到如图:
创业和打工的想法有什么不同 数组和指针的区别

文章插图
可以看到,如图所示与代码7-9行的注释一致 。也就是指针的定义 。没问题 。
数组的地址
通常我们不会用到数组的地址,但是我们这里为了与指针地址进行对比,我们有如下代码:
int arr[2] = {1,2};int arr_val;int **parr;int main(){arr_val = (int)arr;parr = (int**)&arr;}
得到:
创业和打工的想法有什么不同 数组和指针的区别

文章插图
我们看到:
因arr_val=(int)var; 且arr_val为0xa0000000,即使说arr的值就是0xa0000000,也就是arr的第0个元素的地址 。因parr = (int**)&arr; 且parr为0xa0000000,即使说arr的地址就是0xa0000000,也就是arr的第0个元素的地址 。
总结起来就是:数组变量的值==数组变量的地址==数组变量第0个元素的地址 。
从这里可以看到数组与指针的不同:指针本身就是一个变量,指针的地址就是一个变量的地址,肯定是与这个指针变量本身的值是不相同的;但数组变量只是它第0个元素的别名,数组的地址就是它第0个元素的地址,表示用这个变量可以依次从0开始访问后面的各个元素而已 。
我们再从汇编的角度分析这个不同:
对于数组:
00000020 <main>: 20: e52db004 push {fp}; (str fp, [sp, #-4]!) 24: e28db000 add fp, sp, #0 28: e59f2024 ldr r2, [pc, #36] ; 54 <main+0x34> 将0xa0000000给r2 2c: e59f3024 ldr r3, [pc, #36] ; 58 <main+0x38> 将0xa0000008的值给r3 30: e5832000 str r2, [r3] ; 将0xa0000000放到parr所在地址0xa0000008 34: e59f3020 ldr r3, [pc, #32] ; 5c <main+0x3c> 将0xa000000c的值给r3 38: e59f2014 ldr r2, [pc, #20] ; 54 <main+0x34> 将0xa0000000给r2 3c: e5832000 str r2, [r3] ; 将0xa0000000放到arr_val所在地址0xa000000c 40: e3a03000 mov r3, #0 44: e1a00003 mov r0, r3 48: e28bd000 add sp, fp, #0 4c: e49db004 pop {fp}; (ldr fp, [sp], #4) 50: e12fff1e bx lr 54: a0000000 .word 0xa0000000 ; 变量arr所在地址 58: a000000c .word 0xa000000c ; parr所在地址5c: a0000008 .word 0xa0000008 ; 变量arr_val所在地址