0

我最近了解到,可以使用指针更改 c 中的常量值,但对于字符串文字却不可能。可能的解释在于常量和其他字符串在空间中的可修改区域中分配空间,而字符串文字在空间中的不可修改区域(可能是代码段)中分配空间。我编写了一个程序来显示这些变量的地址。输出也显示出来。

#include <stdio.h>
int x=0;
int y=0;

int main(int argc, char *argv[])
{
    const int a =5;
    const int b;
    const int c =10;
    const char *string = "simar";   //its a literal, gets space in code segment
    char *string2 = "hello";
    char string3[] = "bye"; // its array, so gets space in data segment
    const char string4[] = "guess";
    const int *pt;
    int *pt2;

    printf("\nx:%u\ny:%u Note that values are increasing\na:%u\nb:%u\nc:%u Note that values are dec, so they are on stack\nstring:%u\nstring2:%u Note that address range is different so they are in code segment\nstring3:%u Note it seems on stack as well\nstring4:%u\n",&x,&y,&a,&b,&c,string,string2,string3,string4); 
}

在此处输入图像描述

请解释这些变量究竟在哪里获得空间?全局变量从哪里获得空间,常量从哪里获得,字符串文字从哪里获得?

4

2 回答 2

5

“可能”夸大了情况。

您可以编写尝试修改 const 对象的代码(例如,通过将其地址转换为指向非 const 类型的指针)。您还可以编写尝试修改字符串文字的代码。

在这两种情况下,您的代码都有未定义的行为,这意味着标准并不关心发生了什么。实现可以做它喜欢做的事情,而发生的事情通常是其他重要事情的意外副作用。你不能依赖这种行为。简而言之,该代码是错误的。这对于定义为 的对象const和字符串文字都是如此。

可能在特定实现上,效果是更改对象或文字。可能是在另一个实现中,您遇到访问错误并且程序崩溃。可能是在第三种实现中,您有时会得到一种行为,而有时会得到另一种行为。可能会发生完全不同的事情。

它是特定于实现的,变量在哪里获得空间,但在典型的实现中:

  • x并且y在可修改的数据段中
  • a在堆栈上。如果不是因为您获取了它的地址,那么可以完全优化变量存储,并且5在编译器为使用a.
  • b我认为是一个错误——未初始化的 const 对象。也许这是允许的,但编译器可能应该发出警告。
  • c在堆栈上,与 相同a
  • 文字“simar”等都在代码段、只读数据段或可修改数据段中,如果实现不打扰rodata的话。
  • string3并且string4是堆栈上的数组。每个都是通过复制字符串文字的内容来初始化的。
于 2012-08-15T12:04:59.200 回答
1

我最近了解到可以使用指针更改 c 中的常量值

这样做会导致未定义的行为(参见标准 6.7.3),这意味着任何事情都可能发生。实际上,您可以在某些基于 RAM 的系统上修改常量。

字符串文字不可能

这同样是未定义的行为,可能有效,也可能无效,或者可能导致硬盘冒出蓝烟。

可能的解释在于常量和其他字符串在空间中的可修改区域中分配空间,而字符串文字在空间中的不可修改区域中分配空间

这取决于系统。在某些系统上,它们都位于常量/虚拟 RAM 段中,在某些系统上,它们可能位于非易失性闪存中。如果不指定您正在谈论的系统,则讨论事物最终在内存中的位置是没有意义的。没有通用案例。

于 2012-08-15T12:02:01.037 回答