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

数组和指针的区别(创业和打工的想法有什么不同)在《C语言揭秘:各种数据类型》中已经介绍了指针和数组,但在实际编码中指针和数组容易被错误使用,本文就有必要从不同场景分析它们互通性和独特性。访问指针所指变量C语言中,指针是指向其他变量的变量。比

在《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; // 数组下标方式}

得到:

C语言揭秘:指针和数组

11行是正常的解引用方式,好理解。

重点注意第12行,采用了数组下标的方式给n2赋值,可以看到与上图中0xa0000004中的值0x8匹配,说明赋值成功。即这种情况下,解引用和数组下标方式通用。

访问数组元素

int arr1[2] = {1,2};int arr2[2] = {3,4};int main(){ *arr1 = 5; arr2[0] = 8;}

得到结果:

C语言揭秘:指针和数组

可以看到6、7行都可以成功给数组中第一个元素赋值。因此2种方式通用。

指针的地址

指针作为一个变量也可以取其地址,那就是二重指针,比如:

int n1 = 0xbabebeaf;int *pn1;int **ppn1; // 二重指针int main(){ n1 = 5;// n1的值为5 pn1 = &n1; // pn1的地址为n1的地址0xa0000000 ppn1 = &pn1; //取指针变量pn1的地址赋给ppn1,即ppn1的值为0xa0000008}

得到如图:

C语言揭秘:指针和数组

可以看到,如图所示与代码7-9行的注释一致。也就是指针的定义。没问题。

数组的地址

通常我们不会用到数组的地址,但是我们这里为了与指针地址进行对比,我们有如下代码:

int arr[2] = {1,2};int arr_val;int **parr;int main(){ arr_val = (int)arr; parr = (int**)&arr;}

得到:

C语言揭秘:指针和数组

我们看到:

因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所在地址

从上面反编译的注释中可以看到,对于数组来说&arr的值与arr的值的处理方式完全相同。

对于指针,反汇编:

00000020 <main>: 20: e52db004 push {fp} ; (str fp, [sp, #-4]!) 24: e28db000 add fp, sp, #0 28: e59f3030 ldr r3, [pc, #48] ; 60 <main+0x40> r3 = 0xa0000000 2c: e3a02005 mov r2, #5 ; r2 = 5 30: e5832000 str r2, [r3] ; 0xa0000000处写入5 34: e59f3028 ldr r3, [pc, #40] ; 64 <main+0x44> r3= 0xa0000008 38: e59f2020 ldr r2, [pc, #32] ; 60 <main+0x40> r2 = 0xa0000000 3c: e5832000 str r2, [r3] ; 0xa0000008处写入 0xa0000000,即pn1=&n1 40: e59f3020 ldr r3, [pc, #32] ; 68 <main+0x48> r3 = 0xa0000004 44: e59f2018 ldr r2, [pc, #24] ; 64 <main+0x44> r2= 0xa0000008 48: e5832000 str r2, [r3] ; 0xa0000004处写入0xa0000008,即ppn1 = &pn1 4c: e3a03000 mov r3, #0 50: e1a00003 mov r0, r3 54: e28bd000 add sp, fp, #0 58: e49db004 pop {fp} ; (ldr fp, [sp], #4) 5c: e12fff1e bx lr 60: a0000000 .word 0xa0000000 ; n1 所在地址 64: a0000008 .word 0xa0000008 ; pn1所在地址 68: a0000004 .word 0xa0000004 ; ppn1所在地址

上面的注释完整解释了一级指针和二级指针的使用方式,完美符合指针的定义。

指针和数组作为函数参数指针作为函数参数

比如下面函数inc实现的功能是将pn所指向的整型数加一:

void inc(int *pn){ *pn = *pn+1;}int n = 5;int main(){ inc(&n);}

反汇编后:

00000020 <inc>: 20: e52db004 push {fp} ; (str fp, [sp, #-4]!) 24: e28db000 add fp, sp, #0 28: e24dd00c sub sp, sp, #12 2c: e50b0008 str r0, [fp, #-8] ; pn = r0 = 0xa0000000 30: e51b3008 ldr r3, [fp, #-8] ; r3 = pn = 0xa0000000 34: e5933000 ldr r3, [r3] ; r3 = RAM[0xa0000000] = 5 38: e2832001 add r2, r3, #1 ; r2 = r3+1 = 6 3c: e51b3008 ldr r3, [fp, #-8] ; r3 = pn = 0xa0000000 40: e5832000 str r2, [r3] ; RAM[0xa0000000] = r2 = 6,即n=6 44: e1a00000 nop ; (mov r0, r0) 48: e28bd000 add sp, fp, #0 4c: e49db004 pop {fp} ; (ldr fp, [sp], #4) 50: e12fff1e bx lr00000054 <main>: 54: e92d4800 push {fp, lr} 58: e28db004 add fp, sp, #4 5c: e59f0014 ldr r0, [pc, #20] ; 78 <main+0x24> r0 = &n = 0xa0000000 60: ebffffee bl 20 <inc> ; 跳转到inc函数 64: e3a03000 mov r3, #0 68: e1a00003 mov r0, r3 6c: e24bd004 sub sp, fp, #4 70: e8bd4800 pop {fp, lr} 74: e12fff1e bx lr 78: a0000000 .word 0xa0000000 ; &n = 0xa0000000

得到结果:

C语言揭秘:指针和数组

详细分析见上面汇编的注释。我们看到,在inc中做+1操作是直接在pn变量所指向的内存0xa0000000上操作,没有在内存做任何拷贝。

可以得到结论:

将指针作为函数参数时,就是把实参(一个地址值&n)传给形参(pn),操作*pn = *pn+1;就是将pn所指向的变量n,加1。

将指针作为函数参数的场景包括:

通过调用函数修改实参本身的值;返回大于一个参数是;为了更好的性能,需要零拷贝;参数是一个结构体,传值繁杂且低效;参数时一个函数指针,作为回调函数时。数组作为函数参数

还是刚才的功能,参数换成数组形式:

void inc(int pn[]){ pn[0] = pn[0]+1;}int n = 5;int main(){ inc(&n);}

从C语言的角度分析,前面有结论,数组名就是它的第0个元素的别名,那在该代码中,将&n传给inc,那pn的第0个元素就是n,因此:pn[0] = pn[0]+1; 就是n=n+1; 所以结果同指针情况。

生成反汇编同指针情况完全一样,直接参考上面汇编。

所以得到结论:

指针和数组作为函数参数是等价的。

【版权声明】叽叽歪歪吧提醒您:请在浏览本网站关于《数组和指针的区别(创业和打工的想法有什么不同)》信息时,请您务必阅读并理解本声明。本站部分内容以及图片来源于商家投稿和网络转载,如网站发布的有关的信息侵犯到您的权益,请及时与我们取得联系,邮箱:20451 17252#qq。com,我们会尊重您的决定并当天作出删除处理。

(0)
上一篇 2022年3月4日 11:33:03
下一篇 2022年3月4日 11:53:03

相关推荐

  • 欧意抽油烟机好不好(欧意268抽油烟机)

    欧意抽油烟机好不好(欧意268抽油烟机)在大互联的时代下,势不可挡的智能化浪潮,已经从单一的厨电产品,放大至整体厨房领域。老板的ROKI智能烹饪系统、海尔的U+智慧厨房、美的智慧营养解决方案……近两年,在主流大牌们的你争我夺下,智能厨房尽管

    2022年2月19日
    27
  • 腰果放置久了(腰果花)

    腰果放置久了(腰果花)对于腰果我们大家都非常的熟悉,腰果是一种很有营养的坚果类食物。腰果是很多人都喜欢吃的食物,有很多人都把腰果当做零食食用,那腰果上有黑点能吃吗?腰果上黑点是什么?下面wed114结婚网小编为大家带来详细内容。腰果上有黑点

    2022年2月14日
    19
  • 菜市场卖什么最吸引人 天冷菜市场卖什么最畅销

    菜市场卖什么最吸引人(天冷菜市场卖什么最畅销)集市承载着人们的美好生活,亦是都市生活的安慰剂,市民们穿梭于熙熙攘攘的人群,往来于肉蛋奶菜各“味”其职的摊位,叫卖声、喧闹声、寒暄声混杂在一起,十分的热闹。冬天到了,气温越来越低,农安的室外温度

    2022年4月16日 生活小百科
    3
  • 逝者如斯夫什么意思 缅怀逝者的句子

    逝者如斯夫什么意思(缅怀逝者的句子)逝者如斯夫!不舍昼夜名句的诞生子在川上1曰:“逝2者如斯3夫!不舍4昼夜。”——子罕·十六完全读懂名句1.川上:河川岸边的意思。2.逝:往,去。3.斯:这个。4.舍:停止之意。孔子在河边感叹道:“一去不复

    2022年5月8日
    7
  • 侦探公司哪家最可靠 找侦探公司

    侦探公司哪家最可靠(找侦探公司)因为国际化交流的增多,曾经出现在电影电视剧里的所谓“私家侦探”也已经渐渐的融入了我们的生活。大比例都是在国外,其实国内的“私家侦探”在大城市遍地都是,只是质量参差不齐。目前国内的法律法规对这一行业并没有任何规

    2022年4月10日
    10
  • 特种作战学院(中国15个特战旅排名)

    特种作战学院(中国15个特战旅排名)现在全军有2所特种作战院校:分别是1、中国人民解放军陆军特种作战学院主要承担陆军特种作战指挥军官、全军狙击手培训,以及海军陆战队、空降兵部队部分指挥生长军官本科基础教育任务。2017年以原解放军特种作战学

    2022年2月16日 生活小百科
    259
  • 农村创业故事分享 我的农村创业经历

    农村创业故事分享(我的农村创业经历)2021年乡村振兴产业英雄案例征集活动火热进行中在各位用户朋友们的积极参与下我们收到了数百个创业案例经过汇总和评选30位优秀产业带头人脱颖而出现在进入投票阶段票数排名前十位的产业带头人将会获得一亩田颁发的

    2022年4月11日 生活小百科
    19
  • 工业盐的作用(工业盐在家庭中有何用途)

    工业盐的作用(工业盐在家庭中有何用途)工业盐在工业上的用途很广,是化学工业的最基本原料之一,被称为“化学工业之母”。基本化学工业主要产品中的盐酸、烧碱、纯碱、氯化铵、氯气等主要是用工业盐为原料生产的。那工业盐到底有什么用途呢?一起看下吧!一

    2022年2月25日
    17
  • 泰坦尼克号真相(泰坦尼克号富人存活率)

    泰坦尼克号真相(泰坦尼克号富人存活率)泰坦尼克号这个名字相信很多人都听过,不过很多人对其第一印象都是美国所拍摄的爱情电影,这在当年的确是经典之作,甚至到现在依然被许多人津津乐道。这部电影乃是根据真实事件改编而成,远在1912年4月15日,泰

    2022年2月16日 生活小百科
    21
  • 微信同步登录监控(微信内容可以监控吗?)

    微信同步登录监控(微信内容可以监控吗?)监测是目前企业非常需要的系统。在营销时代,职员们利用营销过程,遇到顾客约定、虐待顾客、消极怠工、生产力下降、恶意删除朋友、删除聊天等各种问题,所以推荐这里的红鹰工作手机也无妨。监视手机风控客户的资料严

    2022年3月10日
    13

发表回复

登录后才能评论