【问题标题】:Storing strings in stack vs code section in C?在C中将字符串存储在堆栈与代码部分中?
【发布时间】:2020-04-07 04:33:25
【问题描述】:

我目前在 C 类中,对字符串文字的存储位置感到非常困惑。我知道字符串只是一个字符数组,所以类似于

char c[5] = {'A','B','C','D', 0};

等价于

char* c = "ABCD";

编辑:后续问题:

char c[5] = {'A','B','C','D', 0};

如果我现在说 c+1,这是指向字符“B”的指针吗?但是“B”在堆栈中吗?还是在内存的代码部分?

但是当我们说字符串字面量存储在内存的代码部分时,我总是对它的含义感到困惑。

我理解栈和堆的区别,但是对内存的代码段的概念我没把握。

例如,我知道,在上面的示例中,c 只是一个堆栈变量。美好的。但是如果我说 c[0] 呢?这是否存储在内存的代码部分中?或者,在我给出的第二个例子中,使用 char * c = "ABCD",c 本身是一个堆栈变量,但它指向内存代码段中的字符?

我完全糊涂了,任何见解都将不胜感激。

谢谢

【问题讨论】:

  • 前两个示例 not 与您的声明相反,因为在第一种情况下,它是一个字符串 constant (可能被存储在代码部分),而第二个是初始化数组。
  • 如果你在函数内部声明这个char c[5] = {'A','B','C','D', 0};(例如main()),它将在堆栈中。在这种情况下,char* c = "ABCD";“ABCD”将在您编译程序时存储在内存中。但是“ABCD”的地址将存储在变量c内的堆栈中(如果您在函数内声明此变量)。
  • 嗯 Vladimir 是的,这是有道理的,那么如果我声明 char c[5] = {'A', 'B', 'C', 'D', 0}; c+1 会指向什么?它指向的'B'是否在堆栈中?还是在代码中?
  • c 存储在堆栈中。如果您这样做c+1,您将获得第二项“B”的地址。当然这个地址会在栈中,因为变量c在栈中。

标签: c arrays char c-strings string-literals


【解决方案1】:

……类似

char c[5] = {'A','B','C','D', 0};

等价于

char* c = "ABCD";

没有。第一个将c 定义为一个由5 个char 组成的数组,它将使用显示的值进行初始化。如果此声明出现在函数之外,c 将具有静态存储持续时间。它将在程序开始时初始化一次,并将在程序的整个执行过程中存在。在常见的 C 实现中,它将存储在初始化数据部分中。如果此声明出现在函数中,c 将具有自动存储持续时间。每次执行到达声明时都会初始化它。初始值的存储方式取决于 C 实现——它们可能内置在初始化数组的指令中,或者它们可能存储在常量数据部分中,以便程序可以将它们从那里复制到 @987654327 的新实例@ 每当创建一个。

第二个将c 定义为指向char 的指针。字符串字面量名义上定义了一个静态存储持续时间的数组。在常见的 C 实现中,如果实际需要该数组(优化可能使其变得不必要),该数组将存储在常量数据部分中。 c 被初始化为指向该数组的第一个字符。如果这个声明出现在函数之外,c 具有静态存储持续时间,所以在程序启动时初始化一次。如果它出现在函数内部,则c 具有自动存储持续时间,并且每次执行到达声明时都会创建并初始化它。无论哪种情况,它都被初始化为指向由字符串字面量定义的数组的第一个字符。

编辑:后续问题:

char c[5] = {'A','B','C','D', 0};

如果我现在说 c+1,这是指向字符“B”的指针吗?但是“B”在 > 堆栈中吗?还是在内存的代码部分?

c+1 指向c[1]。如果c 是在任何函数之外定义的,那么在常见的C 实现中,编译器/程序在某些部分中用于静态数据,因此c+1 指向该部分。如果c 是在函数内部定义的,那么在常见的C 实现中,它位于堆栈上,因此c+1 指向堆栈。 (请注意,根据上下文,优化可能不需要存储所有c 或将c+1 维护为指针。)

但是当我们说字符串 > 文字存储在内存的代码部分时,我总是对它的含义感到困惑。

字符串字面量定义了一个静态存储持续时间的数组。在常见的 C 实现中,它们将存储在常量数据部分中。这与代码部分不同。它们都是只读的,但代码部分是可执行的。一些计算机体系结构没有区分它们的方法,当然可以将只读数据存储在代码段中,但通常最好有单独的段。

与 C 中的所有内容一样,源代码的名义含义就是它在 C 标准定义的抽象机器中的行为方式。只要生成的程序在可观察的效果(包括可见的输入和输出)方面具有相同的行为,编译器就可以进行优化。优化可能会导致抽象机中静态存储时长的字符串在实际程序中存在很大差异。

【讨论】:

    【解决方案2】:

    等价于

    在功能上等价于将存储在内存中某处,但类型不同(一个是数组,另一个是指针)并且它们最终的位置是(通常)不是同一个地方。

    但是如果我说 c[0] 呢?这是存储在内存的代码部分吗?

    c[0] 只是一个表达式,它引用数组中的第一个字符(或者对于指针,它指向的第一个字符)。表达式本身不存储在任何地方,但它表示的字符是数组的第一个字符(同上)。例如,如果字符串在堆栈中结束,那么c[0] 将表示第一个字符将在堆栈中。

    当我们说字符串字面量存储在内存的代码段中是什么意思。

    二进制文件(通常)由几个部分组成。其中之一是包含代码的代码(您的 CPU 将运行的指令)。还有其他部分可用于存储字符串文字。这一切如何运作取决于您的架构和操作系统。

    【讨论】:

    • 感谢您的回复。所以,换个说法,如果我有 char c[5] = {'A','B','C','D', 0}; c[0] 代表的字符是存储在内存的代码段中的吗?还是在堆栈上?
    • @Evan 不客气!正如答案所解释的,这取决于。例如,如果c 放在堆栈中,那么c[0] 是堆栈中的一个字节(为c 数组保留的第一个字节)。
    • 嗯嗯,“如果 c 被放入堆栈”是什么意思?比如什么时候 c 不会被放入堆栈?
    • @Evan 好吧,如果它是全局的,它就不会在堆栈中。但即使那是编译器的细节,而不是 C 本身的细节。
    猜你喜欢
    • 2012-04-17
    • 1970-01-01
    • 2017-11-16
    • 2016-01-12
    • 1970-01-01
    • 2011-12-28
    • 2023-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多