在上一篇博文  代码优化小技巧(持续更新......) 第三条关于数组和指针谁更高效, 意犹未尽, 决定单独拉出一篇来讲

1. 数组和指针操作对比
#include <stdio.h>

int main()
{
char *char_p, char_arr[]={,,};
short *short_p, short_arr[]={,,};
int *int_p, int_arr[]={,,}; char_p=char_arr;
short_p=short_arr;
int_p=int_arr; printf("111\n");
(*(char_p+)) ++;
printf("222\n");
char_arr[] ++; printf("111\n");
(*(short_p+)) ++;
printf("222\n");
short_arr[] ++; printf("111\n");
(*(int_p+)) ++;
printf("222\n");
int_arr[] ++; return ;
}

编译和反汇编

<main>:
: push %rbp
: e5 mov %rsp,%rbp
40059a: ec sub $0x60,%rsp
40059e: 8b mov %fs:0x28,%rax
4005a5:
4005a7: f8 mov %rax,-0x8(%rbp)
4005ab: c0 xor %eax,%eax
4005ad: c7 f0 movl $0x0,-0x10(%rbp)
4005b4: c6 f4 movb $0x0,-0xc(%rbp)
4005b8: c6 f1 movb $0x1,-0xf(%rbp)
4005bc: c6 f2 movb $0x2,-0xe(%rbp)
4005c0: c7 c0 movq $0x0,-0x40(%rbp)
4005c7:
4005c8: c7 c8 movw $0x0,-0x38(%rbp)
4005ce: c7 c0 movw $0x1,-0x40(%rbp)
4005d4: c7 c2 movw $0x2,-0x3e(%rbp)
4005da: c7 c4 movw $0x3,-0x3c(%rbp)
4005e0: c7 d0 movq $0x0,-0x30(%rbp)
4005e7:
4005e8: c7 d8 movq $0x0,-0x28(%rbp)
4005ef:
4005f0: c7 e0 movl $0x0,-0x20(%rbp)
4005f7: c7 d0 movl $0x2,-0x30(%rbp)
4005fe: c7 d4 movl $0x3,-0x2c(%rbp)
: c7 d8 movl $0x4,-0x28(%rbp)
40060c: 8d f0 lea -0x10(%rbp),%rax
: a8 mov %rax,-0x58(%rbp)
: 8d c0 lea -0x40(%rbp),%rax
: b0 mov %rax,-0x50(%rbp)
40061c: 8d d0 lea -0x30(%rbp),%rax
: b8 mov %rax,-0x48(%rbp)
: bf mov $0x400754,%edi
: e8 fe ff ff callq <puts@plt>
40062e: 8b a8 mov -0x58(%rbp),%rax
: c0 add $0x2,%rax
: 0f b6 movzbl (%rax),%edx
: c2 add $0x1,%edx
40063c: mov %dl,(%rax)
40063e: bf mov $0x400758,%edi
: e8 fe ff ff callq <puts@plt>
: 0f b6 f2 movzbl -0xe(%rbp),%eax
40064c: c0 add $0x1,%eax
40064f: f2 mov %al,-0xe(%rbp)
: bf mov $0x400754,%edi
: e8 fe ff ff callq <puts@plt>
40065c: 8b b0 mov -0x50(%rbp),%rax
: c0 add $0x4,%rax
: 0f b7 movzwl (%rax),%edx
: c2 add $0x1,%edx
40066a: mov %dx,(%rax)
40066d: bf mov $0x400758,%edi
: e8 e9 fd ff ff callq <puts@plt>
: 0f b7 c4 movzwl -0x3c(%rbp),%eax
40067b: c0 add $0x1,%eax
40067e: c4 mov %ax,-0x3c(%rbp)
: bf mov $0x400754,%edi
: e8 d4 fd ff ff callq <puts@plt>
40068c: 8b b8 mov -0x48(%rbp),%rax
: c0 add $0x8,%rax
: 8b mov (%rax),%edx
: c2 add $0x1,%edx
: mov %edx,(%rax)
40069b: bf mov $0x400758,%edi
4006a0: e8 bb fd ff ff callq <puts@plt>
4006a5: 8b d8 mov -0x28(%rbp),%eax
4006a8: c0 add $0x1,%eax
4006ab: d8 mov %eax,-0x28(%rbp)
4006ae: b8 mov $0x0,%eax
4006b3: 8b 4d f8 mov -0x8(%rbp),%rcx
4006b7: 0c xor %fs:0x28,%rcx
4006be:
4006c0: je 4006c7 <main+0x131>
4006c2: e8 a9 fd ff ff callq <__stack_chk_fail@plt>
4006c7: c9 leaveq
4006c8: c3 retq
4006c9: 0f 1f nopl 0x0(%rax)

x86编译和反汇编

0000842c <main>:
842c: e92d4800 push {fp, lr}
: e28db004 add fp, sp, #
: e24dd038 sub sp, sp, # ; 0x38
: e3a03000 mov r3, #
843c: e50b3018 str r3, [fp, #-] ; 0xffffffe8
: e3a03000 mov r3, #
: e54b3014 strb r3, [fp, #-] ; 0xffffffec
: e3a03001 mov r3, #
844c: e54b3017 strb r3, [fp, #-] ; 0xffffffe9
: e3a03002 mov r3, #
: e54b3016 strb r3, [fp, #-] ; 0xffffffea
: e24b3024 sub r3, fp, # ; 0x24
845c: e3a02000 mov r2, #
: e5832000 str r2, [r3]
: e2833004 add r3, r3, #
: e3a02000 mov r2, #
846c: e5832000 str r2, [r3]
: e2833004 add r3, r3, #
: e3a02000 mov r2, #
: e1c320b0 strh r2, [r3]
847c: e2833002 add r3, r3, #
: e3a03001 mov r3, #
: e14b32b4 strh r3, [fp, #-] ; 0xffffffdc
: e3a03002 mov r3, #
848c: e14b32b2 strh r3, [fp, #-] ; 0xffffffde
: e3a03003 mov r3, #
: e14b32b0 strh r3, [fp, #-] ; 0xffffffe0
: e24b3038 sub r3, fp, # ; 0x38
849c: e3a02000 mov r2, #
84a0: e5832000 str r2, [r3]
84a4: e2833004 add r3, r3, #
84a8: e3a02000 mov r2, #
84ac: e5832000 str r2, [r3]
84b0: e2833004 add r3, r3, #
84b4: e3a02000 mov r2, #
84b8: e5832000 str r2, [r3]
84bc: e2833004 add r3, r3, #
84c0: e3a02000 mov r2, #
84c4: e5832000 str r2, [r3]
84c8: e2833004 add r3, r3, #
84cc: e3a02000 mov r2, #
84d0: e5832000 str r2, [r3]
84d4: e2833004 add r3, r3, #
84d8: e3a03002 mov r3, #
84dc: e50b3038 str r3, [fp, #-] ; 0xffffffc8
84e0: e3a03003 mov r3, #
84e4: e50b3034 str r3, [fp, #-] ; 0xffffffcc
84e8: e3a03004 mov r3, #
84ec: e50b3030 str r3, [fp, #-] ; 0xffffffd0
84f0: e24b3018 sub r3, fp, #
84f4: e50b3008 str r3, [fp, #-]
84f8: e24b3024 sub r3, fp, # ; 0x24
84fc: e50b300c str r3, [fp, #-]
: e24b3038 sub r3, fp, # ; 0x38
: e50b3010 str r3, [fp, #-]
: e59f00b0 ldr r0, [pc, #] ; 85c0 <main+0x194>
850c: ebffff8f bl <_init+0x20>
: e51b3008 ldr r3, [fp, #-]
: e2833002 add r3, r3, #
: e5d32000 ldrb r2, [r3]
851c: e2822001 add r2, r2, #
: e20220ff and r2, r2, # ; 0xff
: e5c32000 strb r2, [r3]
: e59f0094 ldr r0, [pc, #] ; 85c4 <main+0x198>
852c: ebffff87 bl <_init+0x20>
: e55b3016 ldrb r3, [fp, #-] ; 0xffffffea
: e2833001 add r3, r3, #
: e20330ff and r3, r3, # ; 0xff
853c: e54b3016 strb r3, [fp, #-] ; 0xffffffea
: e59f0078 ldr r0, [pc, #] ; 85c0 <main+0x194>
: ebffff81 bl <_init+0x20>
: e51b300c ldr r3, [fp, #-]
854c: e2833004 add r3, r3, #
: e1d320b0 ldrh r2, [r3]
: e2822001 add r2, r2, #
: e1a02802 lsl r2, r2, #
855c: e1a02822 lsr r2, r2, #
: e1c320b0 strh r2, [r3]
: e59f0058 ldr r0, [pc, #] ; 85c4 <main+0x198>
: ebffff78 bl <_init+0x20>
856c: e15b32b0 ldrh r3, [fp, #-] ; 0xffffffe0
: e2833001 add r3, r3, #
: e1a03803 lsl r3, r3, #
: e1a03823 lsr r3, r3, #
857c: e14b32b0 strh r3, [fp, #-] ; 0xffffffe0
: e59f0038 ldr r0, [pc, #] ; 85c0 <main+0x194>
: ebffff71 bl <_init+0x20>
: e51b3010 ldr r3, [fp, #-]
858c: e2833008 add r3, r3, #
: e5932000 ldr r2, [r3]
: e2822001 add r2, r2, #
: e5832000 str r2, [r3]
859c: e59f0020 ldr r0, [pc, #] ; 85c4 <main+0x198>
85a0: ebffff6a bl <_init+0x20>
85a4: e51b3030 ldr r3, [fp, #-] ; 0xffffffd0
85a8: e2833001 add r3, r3, #
85ac: e50b3030 str r3, [fp, #-] ; 0xffffffd0
85b0: e3a03000 mov r3, #
85b4: e1a00003 mov r0, r3
85b8: e24bd004 sub sp, fp, #
85bc: e8bd8800 pop {fp, pc}
85c0: 000086a0 .word 0x000086a0
85c4: 000086a4 .word 0x000086a4

arm编译和反汇编

横向对比:

  这里可以很明显得出结论: 使用数组操作比指针高效!, 理由很简单, 编译器认为数组偏移多少成员其对于地址都是确定的, 取数组[0]和[3]没有区别就是个地址, 而指针偏移是一个独立行为,

所以要显性执行这个动作, 因此多出这部分指令!

  这个表还有其他有意思的地方, 比如用int变量比char、short高效, char要and或者movzbl屏蔽溢出, short要lsl/lsr左移右移等

  另外就是x86可以直接通过mov操作内存, 而ARM结构采用load-store, 必须先加载到寄存器, 进行操作后再回写内存

2. 指针作为函数参数(x86编译为例)
#include <stdio.h>

void test1(int *p)
{
(*(p+))++;
} void test2(int *p)
{
p[]++;
} int main()
{
char *char_p, char_arr[]={,,};
short *short_p, short_arr[]={,,};
int *int_p, int_arr[]={,,}; char_p=char_arr;
short_p=short_arr;
int_p=int_arr; /* 省略上面测试代码*/ printf("333\n");
test1(int_p);
test2(int_p);
printf("444\n");
test1(int_arr);
test2(int_arr); return ;
}

可以发现test1()、test2()反汇编实现是一样的, 不会因为“形式”上我用数组还是指针, 最终的本质是指针, 而调用无论传的是数组地址还是指针地址, 没有影响, 都是地址值而已

 <test1>:
: push %rbp
: e5 mov %rsp,%rbp
40059a: 7d f8 mov %rdi,-0x8(%rbp)
40059e: 8b f8 mov -0x8(%rbp),%rax
4005a2: c0 add $0x10,%rax
4005a6: 8b mov (%rax),%edx
4005a8: c2 add $0x1,%edx
4005ab: mov %edx,(%rax)
4005ad: nop
4005ae: 5d pop %rbp
4005af: c3 retq 00000000004005b0 <test2>:
4005b0: push %rbp
4005b1: e5 mov %rsp,%rbp
4005b4: 7d f8 mov %rdi,-0x8(%rbp)
4005b8: 8b f8 mov -0x8(%rbp),%rax
4005bc: c0 add $0x10,%rax
4005c0: 8b mov (%rax),%edx
4005c2: c2 add $0x1,%edx
4005c5: mov %edx,(%rax)
4005c7: nop
4005c8: 5d pop %rbp
4005c9: c3 retq 4006e7: e8 fd ff ff callq <puts@plt>
4006ec: 8b b8 mov -0x48(%rbp),%rax
4006f0: c7 mov %rax,%rdi
4006f3: e8 9e fe ff ff callq <test1>
4006f8: 8b b8 mov -0x48(%rbp),%rax
4006fc: c7 mov %rax,%rdi
4006ff: e8 ac fe ff ff callq 4005b0 <test2>
: bf e0 mov $0x4007e0,%edi
: e8 fd ff ff callq <puts@plt>
40070e: 8d d0 lea -0x30(%rbp),%rax
: c7 mov %rax,%rdi
: e8 7c fe ff ff callq <test1>
40071a: 8d d0 lea -0x30(%rbp),%rax
40071e: c7 mov %rax,%rdi
: e8 8a fe ff ff callq 4005b0 <test2>
3. 数组作为函数参数(x86编译为例)
代码和上面一样就不贴了, 只是将参数改成数组
/*
void test1(int *p)
{
(*(p+4))++;
} void test2(int *p)
{
p[4]++;
}
*/
void test1(int p[])
{
(*(p+))++;
} void test2(int p[])
{
p[]++;
}

反汇编的结果发现和上面函数形参是指针的一模一样!  也就是说虽然我的参数看起来像数组, 但实际上由于没有指定成员数量实际分配内存, 所以编译器还是把参数当做指针对待!

结论:

  a. “真实”数组操作比指针高效

  b. 有些看起来像数组, 实质是指针的, 指令走的还是指针那一套, 无论语法写的是*p++还是p[i]

C语言数组操作和指针操作谁更高效的更多相关文章

  1. C/C++——C语言数组名与指针

    版权声明:原创文章,转载请注明出处. 1. 一维数组名与指针 对于一维数组来说,数组名就是指向该数组首地址的指针,对于: ]; array就是该数组的首地址,如果我们想定义一个指向该数组的指针,我们可 ...

  2. 向php数组添加元素的方法哪种更高效

    $arr = array(); // 第一种 array_push($arr, 'test'); // 第二种 $arr[] = 'test'; 参考PHP官方文档:http://php.net/ma ...

  3. C语言指针操作

    欢迎访问我的新博客:http://www.milkcu.com/blog/ 原文地址:http://www.milkcu.com/blog/archives/pointer-manipulation. ...

  4. 【Go语言】集合与文件操作

    本文目录 1.数据集合的主要操作 1_1.字典的声明 1_2.字典的初始化和创建 1_3.字典的访问和操作 1_4.其他类型的数据集 2.文件操作 2_1.文件操作概述os包和path包 2_2.文件 ...

  5. C语言 数组名不是指针

    今天上计算机系统课的时候老师讲到了C中的聚合类型的数据结构.在解释数组名的时候说"数组名是一个指针,指向该数组的第一个元素",附上ppt(第二行): 我觉得这是不正确的,是一个常见 ...

  6. 深入解析C语言数组和指针

    概述 指针是C语言的重点,同时也是让初学者认为最难理解的部分.有人说它是C语言的灵魂,只有深入理解指针才能说理解了C语言.暂且撇开这些观点不谈.这章是我在阅读<C和指针>这本书的读书笔记. ...

  7. 【嵌入式开发】C语言 内存分配 地址 指针 数组 参数 实例解析

    . Android源码看的鸭梨大啊, 补一下C语言基础 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/detai ...

  8. 别人不会给你说的---C语言中数组名和指针的区别 及 sizeof用法

    引自: http://blog.csdn.net/tianyue168/article/details/5781924 #i nclude <iostream.h> int  main( ...

  9. C语言 内存分配 地址 指针 数组 参数 实例解析

    . Android源码看的鸭梨大啊, 补一下C语言基础 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/detai ...

随机推荐

  1. HCNA(华为)_DHCP篇

    在大型的企业网络中,会有大量的主机或设备需要获取IP地址等网络参数.如果采用手工配置,工作量大 且不好管理,如果有用户擅自修改网络参数,还有可能会造成IP地址冲突等问题.使用动态主机配置协DHCP 来 ...

  2. Oracle事务与锁 知识点摘记

    事务:事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml语句要么全部成功要么全部失败. 说明:一组SQL,一个逻辑工作单位,执行整体修改或者整体回退. 事务的相关概念: 1.事务的提 ...

  3. vue 实现图片上传与预览,以及清除图片

    vue写原生的上传图片并预览以及清除图片的效果,下面是demo,其中里面有vue获取input框value值的方法以及vue中函数之间的调用 <!DOCTYPE html> <htm ...

  4. 在Codeblocks下配置GoogleTest单元测试工具

    开发工具 我和我的组员的都是使用的是大一老师推荐的codeblocks,所以,就愉快的决定了工具统一为codeblocks,语言C++. 测试单元 老师推荐的是JUnit和VSTS工具,但同学们从大一 ...

  5. javaWeb+servlet+mysql实现简单的企业员工管理系统

    企业员工信息管理系统 一.源码描述       本程序为企业员工信息管理系统.是javaEE一个系统,主要实现登录功能和两个模块信息的增删改查.可以作为JAVAweb学习,也可在原有基础上进行深一步的 ...

  6. ubuntu解压时中文出现乱码

    一.乱码类似这样的:╫╩┴╧╖┤╤▌▓т╒╛╦┘╢╚│ 今天遇到需要上传十几G的图片,在wins上压缩成zip格式,在上传到服务器上,结果出现乱码.然后各种百度心塞. 最初查到原因: 这个主要是因为z ...

  7. Live2D插件--漂浮的二次元小姐姐

    这个插件找了很久,都没找到,今天偶然翻到一个小哥的博客发现了这个,果断偷走. 教程转自简书:https://www.jianshu.com/p/1cedcf183633 还有这些,你可能有用 修改位置 ...

  8. C语言复习3_条件结构

    if条件结构 if else 结构一般处理区间情况 #include <stdio.h> #include <stdlib.h> int main() { //打印剧情 dou ...

  9. 轮播效果/cursor

    cursor属性:改变鼠标中的属性 例如: cursor:pointer(鼠标移动上去变小手) <!doctype html> <html> <head> < ...

  10. CABaRet: Leveraging Recommendation Systems for Mobile Edge Caching

    CABaRet:利用推荐系统进行移动边缘缓存 本文为SIGCOMM 2018 Workshop (Mobile Edge Communications, MECOMM)论文. 笔者翻译了该论文.由于时 ...