char数组的字符串是存在哪里的,是常量区还是栈区?
3 个回答
虽然从常量区拷贝到栈上面肯定没错,但是搞两份拷贝有点浪费,毕竟这个字符串只用在初始化这个局部变量了。所以具体还是看编译器了。
我测试了一下。对于程序:
void foo() { char n[] = "This is a string"; }
如果用 64 位的 WSL 下用 GCC 编译,这个字符串本身是硬编码在指令里面的。图:
注意第 0x17 和 0x25 字节开始的那两条指令的立即数,其实就是 "Thing is a string" 的 ASCII 码:
而对于微软的 CL,
这段代码确实是把字符串存在常量区,然后运行的时候拷贝的:
另外 clang 好像也是写在常量区然后拷贝。就不贴那么多图片了。
肯定是有两份的。
理由很简单:
因为你现在可以修改这个char数组了。
修改常量区内容?怎么想都不太对吧。
好吧其实我推出结果的过程是不严谨哒,我错了……但我觉得这种细究下去太没意思了。
栈虽然不是堆那样动态的,但也是运行时才确定的,栈上的数据没法凭空出现,总得有个源头(除非是一些立即数,被编码到指令里了)。
char[4],其实编码进指令也不是不可以,毕竟也就一个int的大小……但是我想不出编译器这么做的理由——写编译器的人难道就喜欢加班吗……
有一种可能是n就在常量区,没有拷贝。但你可以修改这个数组了,所以显然很矛盾,不const了。
所以就只剩下需要拷贝这么一种可能了。两个地方~~
GCC居然优化到指令里了!可怕……
看你怎么初始化的了,如果用“123”的方式初始化就是在常量区
如果用{'1','2','3'}这种方式初始化就是在栈区