C 中的 String Table 是什么?

What is String Table in C?

char *p = "one two three";

显然,这段代码中的字符串常量存储在字符串table中。什么是“字符串table”?是在heap还是在stack?

信息背景:我在找到了这个信息 自学 C,作者 Hilbert Schildt,第 6 章(使用指针)。

As you know, C allows string constants enclosed between double quotes to be used in a program. When compiler encounters such a string, it stores it in the program's string table and generates a pointer to the string. For this reason, the following program is correct and prints - one two three.

#include<stdio.h>
int main(void){
  char*p = "one two three";
  printf(p);
  return 0;
}

引用段落的意思是程序的一个单独部分。这些字符串常量既不在栈中也不在堆中。

想想程序可能用来存储内容的这些部分(在括号中的可执行文件格式中定义的部分的通用名称):

  • 要执行的机器码(.text);
  • 静态只读值,例如static const变量(.rodata);
  • 具有非零初始值的静态读写变量(.data);
  • 初始值为零的静态读写变量(.bss);
  • 保存return地址、函数参数、局部变量等的堆栈;有时这些是分开的;
  • 堆,如果有的话。

字符串常量通常属于“静态只读值”类别。一些编译器系统将它们与非字符串值分开。

任何编译器系统可能有或没有这些部分,但它们很常见。

无论如何,从这个实现细节中抽象出来。只有当您需要深入了解并且您需要了解特定编译器系统的工作原理时,它才会对您有所帮助。

在抽象层面上,我们可以区分两种情况:

const char* p = "one two three";

字符串常量存储在某处,其地址分配给p。如果用另一个值覆盖此变量,您将丢失地址。

变量 p 需要一个额外的 space。这是哪里,取决于变量。

const char a[] = "one two three";

字符串常量也存储在某处。数组就是在这个地方分配的。只要 a 可见,就可以访问它的字符。

最后说明:字符串常量的字符是只读的。始终使用 const char.

声明各自的变量

这里有两个可能的答案级别:

  1. 语言要求什么
  2. 它通常是如何实现的

重点说第二点,我重点说第一点。

从语言的角度来看,栈和堆是不存在的:它们只是实现细节,一些旧的实现使用了多个堆(本地堆#全局堆)。该语言仅定义持续时间:

  • static duration: lifetime是程序的生命周期
  • 动态持续时间:生命周期在分配后以 malloc 开始并以 free
  • 结束
  • 自动:生命周期从声明变量的 bloc 开始,到 bloc 结束。

字符串文字(用双引号引起来)是一个 常量。这意味着尝试修改它会调用未定义的行为,并且恒定的生命周期是程序的持续时间。如果您多次使用相同的字符串,则未指定它们是否具有相同的地址:

const char *p = "abc";
...
const char *q = "abc"; // p == q may be true or false

注意,字符串文字也可用于初始化数组:

char s[] = "abc";    // array initialization

这里 s 是一个真正的数组(并且可以修改,因为它没有声明为 const),并且取决于它的声明方式,它可以具有自动或静态持续时间。字符串文字是否存在本身(独立于数组)又是一个实现细节。