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

数组和指针的区别(创业和打工的想法有什么不同)在《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

相关推荐

  • 东山是哪里的 广州东山和西关在哪里

    东山是哪里的 广州东山和西关在哪里犹记得当年有个段子,说“小时候读书,自己的梦想就是去东山区上学,可当我考上东山区的学习,却发现东山区已经没有了”。确实,在当年,东山区可是贵族的象征,毕竟住在这里的,不是富贵人家,就是权贵军僚。然而时光荏苒

    2023年3月12日 生活小百科
    1
  • 哪里有放高利贷的 空放贷款三万利息一千

    哪里有放高利贷的 空放贷款三万利息一千提起高利贷,人们深恶痛绝,但是每一行都有他存在的道理,正所谓有需求就会有供给,这也是符合市场经济基本规律的。但是与高利贷接触需要注意那些问题呢?下文将为你一一道来。一、签署空白合同目前高利贷市场存在抵押

    2023年4月14日
    0
  • 跳跳犬哪里 击败跳跳犬

    跳跳犬哪里 击败跳跳犬本文导航跳跳犬阴阳师悬赏封印跳跳犬在哪?跳跳犬在哪比较多?一起跟着蚕豆网小编来看看吧。想和大佬们一起玩耍嘛?想一起交流阴阳师御魂的搭配和培养问题嘛?欢迎加群~跳跳犬发现地点:第1章困难模式、第7章、第十五章跳跳妹妹召唤

    2023年4月10日
    1
  • 心理咨询师在哪里报名 心理咨询师在哪里学

    心理咨询师在哪里报名 心理咨询师在哪里学报考心理咨询师在哪里报名,心理咨询师(psychological consultant)是指运用心理学以及相关知识,遵循心理学原则,通过心理咨询的技术与方法,帮助求助者解除心理问题的专业人员。心理咨询

    2023年5月9日
    3
  • 初三家长会发言稿(食品安全小知识)

    初三家长会发言稿(食品安全小知识)尊敬的老师和各位家长朋友们:晚上好,很荣幸能和大家一起分享我自己教育孩子的经验。我主要从生活和学习,这两个方面和大家一起分享。生活上:1. 树立正确的价值观,告诉她什么是对的,什么是错的。2. 教会她慢慢独

    2022年2月28日
    28
  • 怎么查五个月前微信聊天记录 怎样查一年前的微信聊天记录

    怎么查五个月前微信聊天记录(怎样查一年前的微信聊天记录)如何找回删除的聊天记录?作为我们平时必备的聊天工具,工作和生活都是经常用到。随着时间的推移,使用得越多,自然会存下大量的聊天记录和图片文件等。因此,很容易导致在清理这些聊天记录时很有可

    2022年3月20日
    13
  • 领导发言稿范文(领导讲话稿网站)

    领导发言稿范文(领导讲话稿网站)嗨!近期,笔杆子材料君整理了《审计进点会领导讲话稿汇编(11篇)》,可供大家参考,发散材料写作思维!下载方式 :查看头条简介,加入材料君会员,所有材料的完整电子版均可下载!新加入会员的朋友,请在会员群及时查看

    2022年2月24日
    15
  • 国奥在哪里 现在在哪里

    国奥在哪里 现在在哪里北京时间3月17日,中国97年龄段国奥队将从泰国曼谷飞往吉隆坡,出战3月22日开始在吉隆坡进行的奥运会预选赛第一阶段小组赛。近期状态火热的张玉宁也将南下驰援这支队伍。上月25日,国奥队抵达泰国曼谷展开集训,在泰国期间,

    2023年4月27日
    0
  • 附近哪里有好吃的 附近有什么好吃的请推荐一下

    附近哪里有好吃的 附近有什么好吃的请推荐一下大合集每次推送,都会有一些粉丝在看过后,叹出一口气:“又是吃不了的馆子!啥时候能整理一些大家伙都能吃的馆子呢?”可别觉得小编没有把你们的呼声放在心上。这次专门整理了一个合集,从主食、小吃到聚会、喝

    2023年3月12日 生活小百科
    0
  • ps选项栏在哪里 ps线条图案怎么画

    ps选项栏在哪里 ps线条图案怎么画今天来总结一下工具栏工具栏里的工具包括:移动、选框、套索、快速选择、裁剪、图框、吸管、污点修复画笔、画笔、仿制图章、历史记录画笔、橡皮擦工具、渐变工具、模糊工具、减淡工具、钢笔工具、文字工具、路径选择工具

    2023年2月25日
    0

发表回复

登录后才能评论