一、代码
有关下面代码,p和q的区别是什么:
int main(int argc, char *argv[])
{
char* p = "Hello World";
char q[] = "Hello World";
return 0;
}
二、区别和解释
p和q的区别是:
p 是一个指针,指向程序 只读数据段 的”Hello World”,不可以通过p[x] = x 来赋值,因为不能改变只读数据段的内容。
q 是数组名,也是一个指针,指向栈上从 只读数据段 拷贝来的 “Hello World”
从上面的描述,可以看到,q相对于p是多了一次拷贝的,具体也可以参考[1],[2],最好的方式是汇编gcc -s hello.c -o hello.s
汇编代码之后看看(如果需要汇编代码和c对比阅读,可以使用gcc参数,gcc -c -g -Wa,-adlhn hello.c > hello.s,如果需要Inter风格,可以 -masm=intel):
可以看到第一次指令:movq $.LC0, -8(%rbp)
直接把存在.LC0
的只读数据”Hello World”保存在了寄存器rbp中。
第二次有两个指令,分别是movabsq $8022916924116329800, %rax
和movq %rax, -32(%rbp)
第一句是吧Hello World
[3]移动到了rax
中,然后把rax
的内容移动到了rbp
栈基址寄存器中,也就是前面说的多了一次拷贝,这个操作相当于复制。
三、结论
对于程序中不需要修改的常量字符串,定义成char *
而不是char[]
,可以提升程序的效率,毕竟少一次拷贝,这种情况常见于日志输出的时候。char *init = "init success"
,char *p = "startup fail"
等等。
参考资料:
[1] What is the difference between char s[] and char *s?
[2] What is the difference between these initializations?
[3] 为什么是Hello World?
[4] x64汇编参考
[5] x64寄存器