C中存储的常量变量在哪里?

51 c variables memory-management constants globals

我想知道常量变量存储在哪里.它与全局变量在同一个内存区域吗?还是在堆栈上?

Rob*_*vey 40

它们的存储方式是一个实现细节(取决于编译器).

例如,在GCC编译器中,在大多数机器上,只读变量,常量和跳转表都放在文本部分中.

  • 这可能是一个真正的答案(尽管在指出这一点之后提供流行的实现方法会更有帮助.) (3认同)
  • 简单地陈述“实施细节”虽然是正确的,但可能不是这里的“最佳”答案。我猜想我们正在与一个好奇的初学者打交道,因此,这里的挑战是弄清楚并回答,“我认为你想问*这个*,因此,我认为你想读*那个*”。 (2认同)
  • 有时它不是作为数据存储,而是作为代码存储.即,不是在任何文本或数据段中创建一个int来读取,它只是使用一条指令将常量加载到寄存器中.这比将地址加载到寄存器然后从存储的地址读取数据更小更快.但是,这不一定对数组完成,这可能取决于编译器开关. (2认同)

wra*_*erm 33

根据特定处理器遵循的数据分段,我们有五个部分:

  1. 代码段 - 仅存储代码,ROM
  2. BSS(或符号开始的块) 数据段 - 存储初始化的全局变量和静态变量
  3. 堆栈段 - 存储所有局部变量和有关函数返回地址等的其他信息
  4. 堆段 - 所有动态分配都在这里发生
  5. 数据 BSS(或符号开始符号)段 - 存储未初始化的全局变量和静态变量

请注意,数据和BSS段之间的区别在于前者存储初始化的全局变量和静态变量,后者存储未初始化的变量.

现在,当我必须告诉存储常量变量的位置时,为什么我要讨论数据分段...这是有原因的......

每个段都有一个写保护区域,其中存储了所有常量.

例如:

  • 如果我有一个const int,它是局部变量,那么它存储在堆栈段的写保护区域中.
  • 如果我有一个初始化const var的全局,那么它将存储在数据段中.
  • 如果我有一个未初始化的const var,那么它将存储在BSS段中......

总而言之,"const"只是一个数据QUALIFIER,这意味着首先编译器必须决定变量必须存储哪个段,然后如果变量是const,那么它有资格存储在写保护区域中.那个特定的部分.

  • "如果我有一个初始化const var的全局,那么它存储在BSS中,如果我有一个未初始化的const var,那么它将存储在数据段......"......我认为它应该像unitialised一样 - > bss,初始化 - >数据段 (20认同)
  • 数据段有两部分:初始化和单元化.BSS - >未初始化的数据段. (4认同)
  • 这个答案有交换的bss和数据段.bss由起始地址和分支描述,用于零初始化或未初始化变量,而数据段用于非默认初始化变量. (4认同)
  • "如果我有一个const int,它是局部变量,那么它存储在堆栈段的写保护区域中".堆栈的哪一部分是写保护的? (2认同)
  • 正如@Jonathan Leffler所提到的,bss和数据段是交换的.请更正此内容,因为它会导致混淆 (2认同)

Jon*_*ler 12

考虑一下代码:

const int i = 0;
static const int k = 99;

int function(void)
{
    const int j = 37;
    totherfunc(&j);
    totherfunc(&i);
  //totherfunc(&k);
    return(j+3);
}
Run Code Online (Sandbox Code Playgroud)

通常,i可以存储在文本段中(它是具有固定值的只读变量).如果它不在文本段中,它将存储在全局变量旁边.鉴于它被初始化为零,它可能位于'bss'部分(通常分配归零变量)或'data'部分(通常分配初始化变量).

如果编译器确信它k是未使用的(可能是因为它是单个文件的本地文件),它可能根本不会出现在目标代码中.如果对该totherfunc()引用的调用k没有被注释掉,则k必须在某处分配一个地址 - 它可能与它在同一段中i.

常量(如果它是常量,它仍然是变量吗?)j很可能出现在传统C实现的堆栈上.(如果你在comp.std.c新闻组中询问,有人会提到标准没有说自动变量出现在堆栈上;幸运的是,SO不是comp.std.c!)

请注意,我强制显示变量,因为我通过引用传递它们 - 可能是一个期望指向常量整数的函数.如果从未采取的地址,然后jk可以出代码的完全优化.要删除i,编译器必须知道整个程序的所有源代码 - 它可以在其他翻译单元(源文件)中访问,因此不能轻易删除.如果程序沉迷于共享库的动态加载,那么其中一个库可能依赖于该全局变量.

(文体-变量ij应具备更长,更有意义的名称,这只是一个例子!)


Mic*_*kis 5

取决于您的编译器、系统功能、编译时的配置。

gcc .text除非另有说明,否则只读常量放在该部分。