Xol*_*lve 9 c linux compiler-construction string gcc
当我在我的Linux x86_64机器上编译并运行以下C程序时,由GCC编译:
#include <stdio.h>
int main(void)
{
char *p1 = "hello"; // Pointers to strings
char *p2 = "hello"; // Pointers to strings
if (p1 == p2) { // They are equal
printf("equal %p %p\n", p1, p2); // equal 0x40064c 0x40064c
// This is always the output on my machine
}
else {
printf("NotEqual %p %p\n", p1, p2);
}
}
Run Code Online (Sandbox Code Playgroud)
我总是得到输出:
等于0x40064c 0x40064c
我知道字符串存储在一个常量表中,但与动态分配的内存相比,地址太低了.
与以下程序比较:
#include <stdio.h>
int main(void)
{
char p1[] = "hello"; // char arrar
char p2[] = "hello"; // char array
if (p1 == p2) {
printf("equal %p %p\n", p1, p2);
}
else { // Never equal
printf("NotEqual %p %p\n", p1, p2); // NotEqual 0x7fff4b25f720 0x7fff4b25f710
// Different pointers every time
// Pointer values too large
}
}
Run Code Online (Sandbox Code Playgroud)
两个指针不相等,因为这两个指针可以独立操作.
我想知道GCC如何为这两个程序生成代码,以及它们在执行期间如何映射到内存.由于这已经记录了很多次,所以也欢迎任何文档链接.
rod*_*igo 12
在这两种情况下,编译器"hello"
只.rodata
在程序部分中发出一次字符串的实际字节(rodata代表只读数据).
它们实际上直接从可执行文件映射到内存,有点类似于代码部分.这就是为什么它们与动态分配的远离它们的原因.
然后:
char *p = "hello";
Run Code Online (Sandbox Code Playgroud)
只需初始化p
为此(只读)数据的地址即可.显然:
char *q = "hello";
Run Code Online (Sandbox Code Playgroud)
获取完全相同的地址.这称为字符串池,是编译器的可选流行优化.
但是当你写:
char p[] = "hello";
Run Code Online (Sandbox Code Playgroud)
它可能会生成这样的东西:
char p[6];
memcpy(p, "hello", 6);
Run Code Online (Sandbox Code Playgroud)
作为"hello"
只读汇集字符串的实际地址.
致电memcpy
仅用于说明目的.它可以很好地复制内联,而不是函数调用.
如果以后你做:
char q[] = "hello";
Run Code Online (Sandbox Code Playgroud)
它将定义另一个数组和另一个数组memcpy()
.所以数据相同,但地址不同.
但这些数组变量将驻留在哪里?嗯,这取决于.
.data
可执行文件的部分中,并且它们将保存在那里,其中已存在正确的字符,因此memcpy
在运行时不需要.这很好,因为memcpy
之前必须执行main
.variables of static duration
或类似的东西.关于文档链接,抱歉,我不知道.
但是,如果您可以自己进行实验,谁需要文档?为此,最好的工具是objdump
,它可以反汇编程序,转储数据部分等等!
我希望这能回答你的问题......