gpt4 book ai didi

c - GCC 将字符串常量存储在哪里以及这些指针从何处映射?

转载 作者:IT王子 更新时间:2023-10-29 00:12:05 25 4
gpt4 key购买 nike

当我在我的 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);
}
}

我总是得到这样的输出:

equal 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
}
}

这两个指针不相等,因为这是两个可以独立操作的数组。

我想知道 GCC 是如何为这两个程序生成代码的,以及它们在执行过程中是如何映射到内存的。由于这已经被记录了很多次,因此也欢迎任何指向文档的链接。

最佳答案

在这两种情况下,编译器只在程序的 .rodata 部分发出一次字符串 "hello" 的实际字节 (rodata 代表只读数据)。

它们实际上是直接从可执行文件映射到内存中,有点类似于代码段。这就是为什么它们与动态分配的相差甚远。

然后:

char *p = "hello";

简单地将p初始化为这个(只读)数据的地址。显然:

char *q = "hello";

获取完全相同的地址。这称为字符串池,是编译器的可选流行优化。

但是当你写的时候:

char p[] = "hello";

它可能会产生这样的东西:

char p[6];
memcpy(p, "hello", 6);

作为"hello" 实际上是只读池字符串的地址。

memcpy 的调用仅用于说明目的。它可能很好地内联复制,而不是使用函数调用。

如果你稍后这样做:

char q[] = "hello";

它将定义另一个数组和另一个memcpy()。相同的数据,但不同的地址。

但是这些数组变量将驻留在何处?嗯,这取决于。

  • 如果它们是局部的、非静态的、变量:在堆栈中。
  • 如果它们是全局变量:那么它们将在可执行文件的 .data 部分中,并且它们将保存在那里,其中已经有正确的字符,所以没有 memcpy 在运行时需要。这很好,因为 memcpy 必须在 main 之前执行。
  • 如果它们是局部静态变量:与全局变量完全相同。它们一起被称为静态持续时间变量或类似的东西。

关于文档链接,抱歉,我不知道。

但是如果您可以自己做实验,谁还需要文档呢?为此,最好的工具是 objdump,它可以反汇编程序、转储数据部分等等!

我希望这能回答您的问题...

关于c - GCC 将字符串常量存储在哪里以及这些指针从何处映射?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12393888/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com