C语言开发里指针到底快还是不快?
答:不快,甚至比一般变量要慢!
近日我能看到网上很多人说指针快,我非常纳闷,因为我在学习汇编和cpu底层架构时去翻译过c语言的一些指针代码,给我的答案是:指针从来不快于变量,它比普通变量调用慢一拍。
同时为了验证我是正确的,我去找了许多资料,c语言之父:丹尼斯·里奇也没有说过指针快于普通变量,人家只是说指针更灵活,更便捷。
今天看到很多人在说指针快于普通变量这一点,我感到这样非常误人子弟,说这些话的人可能自己都没有去研究过指针,对指针的理解不是很透彻。
很多人说指针就是地址,这是错误的,首先指针存在于栈中,它自己本身就是变量!指针本身就是一个变量,它跟别的变量的区别在于别的变量是表示值,它是表示地址,编译器在对它进行翻译时会多一层解引用的步骤,也就是这个步骤,注定让它会比别的变量更慢。
这里来说一下变量与指针取值的时候的区别:
1.普通变量
获取变量栈地址->到内存里将值取出
2.指针
获取指针变量栈地址->到内存里将指针变量指向的地址取出->到取出的地址里去将值取出
显而易见,指针很明显更慢!
那些说指针更快的我不清楚为什么这样说,但是有一点,当在c++里,你的类参数是指针或引用时,传递参数不会发生构造函数的深拷贝,这一点的确比普通类更快。
但是在c语言里,这是不可能的!
这里我给大家贴出我在linux环境下使用GCC编译出的代码,代码分别是对变量取值与对指针取值:
如,如下代码:
我们使用GCC翻译成汇编:
gcc -S _test.c -o _test.s
在使用cat命令查看一下:
cat _test.s
有许多gcc自动生成的一些初始化的汇编代码,这里我们先跳过,这里我把与main函数里对应的汇编代码提取出来并加上注释:
//分配4字节的栈空间,并初始化为0
movl $0, -4(%rbp)
//这里就是取变量a的值了
//将变量a的地址放入eax寄存器,相当于传值给printf
movl -4(%rbp), %eax
//调用printf
call printf@PLT
在看看指针的
汇编:
这里我在取出一些相关的汇编
//分配变量a,初始化为0
movl $0, -12(%rbp)
//将变量a的地址放入rax中
leaq -12(%rbp), %rax
//将rax放入存入指针p中
movq %rax, -8(%rbp)
/*
这里就是取指针p的值了
*/
//将指针p指向的地址放入rax中
movq -8(%rbp), %rax
//在将rax中的地址值取到eax中
movl (%rax), %eax
//调用printf
call printf@PLT
这里可以看到,指针确实是多了一个步骤,先将指针指向的地址放入到rax地址中,在将rax地址里的值取出到eax寄存器里供printf作为参数
而普通变量则直接取值
注意上面是at&t汇编,由gcc编译而成,与asm汇编不同。
这样看会更仔细
普通变量:
movl -4(%rbp), %eax
call printf@PLT
指针
movq -8(%rbp), %rax
movl (%rax), %eax
call printf@PLT
指针会更加灵活,同时指针可以指向堆区,用于处理更大的内存。
但是从来没有说指针更快这一说法,只有更灵活,可以指向任意地址
最初开发指针的目的,就是为了能够在单片机中操作任意地址,而不是加快普通变量的访问