我想知道存储常量变量的位置。它与全局变量在同一个内存区域吗?或者它在堆栈中?
答案 0 :(得分:39)
如何存储它们是一个实现细节(取决于编译器)。
例如,在GCC编译器中,在大多数机器上,只读变量,常量和跳转表都放在文本部分中。
答案 1 :(得分:29)
根据特定处理器遵循的数据分段,我们有五个部分:
请注意,数据和BSS段之间的区别在于前者存储已初始化的全局变量和静态变量,后者存储未初始化的变量。
现在,为什么我要谈论数据分段时,我必须告诉存储常量变量的位置......这是有原因的......
每个段都有一个写保护区域,其中存储了所有常量。
例如:
总而言之,“const”只是一个数据QUALIFIER,这意味着首先编译器必须决定变量必须存储哪个段,然后如果变量是const,那么它有资格存储在写入中该特定部分的受保护区域。
答案 2 :(得分:11)
考虑代码:
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);
}
通常,i
可以存储在文本段中(它是具有固定值的只读变量)。如果它不在文本段中,它将存储在全局变量旁边。鉴于它被初始化为零,它可能位于'bss'部分(通常分配归零变量)或'data'部分(通常分配初始化变量)。
如果编译器确信k
未使用(可能是因为它是单个文件的本地文件),它可能根本不会出现在目标代码中。如果对totherfunc()
引用k
的调用未被注释掉,则k
必须在某处分配地址 - 它可能与i
位于同一段中
常量(如果它是常量,它仍然是变量吗?)j
很可能出现在传统C实现的堆栈中。 (如果你在comp.std.c新闻组中询问,有人会提到标准没有说自动变量出现在堆栈上;幸运的是,SO不是comp.std.c!)
请注意,我强制显示变量,因为我通过引用传递它们 - 可能是一个期望指向常量整数的函数。如果从未采用过地址,则j
和k
可以完全从代码中优化出来。要删除i
,编译器必须知道整个程序的所有源代码 - 它可以在其他翻译单元(源文件)中访问,因此不能轻易删除。如果程序沉迷于共享库的动态加载,那就不一定了 - 其中一个库可能依赖于该全局变量。
(从文体上看 - 变量i
和j
应该有更长,更有意义的名称;这只是一个例子!)
答案 3 :(得分:4)
在编译时取决于您的编译器,系统功能和配置。
gcc
puts .text
部分的只读常量,除非另有说明。
答案 4 :(得分:2)
offcourse not,因为
1)bss段存储的非强化变量显然是另一种类型。
(I) large static and global and non constants and non initilaized variables it stored .BSS section.
(II) second thing small static and global variables and non constants and non initilaized variables stored in .SBSS section this included in .BSS segment.
2)数据段是初始化变量,它有3种类型,
(I) large static and global and initlaized and non constants variables its stord in .DATA section.
(II) small static and global and non constant and initilaized variables its stord in .SDATA1 sectiion.
(III) small static and global and constant and initilaized OR non initilaized variables its stord in .SDATA2 sectiion.
我提到上面的小和大意味着取决于编译器,例如小手段<超过8个字节,大意味着>超过8个字节和相等的值。
但我怀疑是局部常数会在哪里发生冲击??????
答案 5 :(得分:1)
通常它们存储在只读数据部分中(而全局变量部分具有写权限)。因此,尝试通过获取其地址来修改常量可能会导致访问冲突,即segfault。
但这取决于您的硬件,操作系统和编译器。
答案 6 :(得分:1)
这主要是一个有根据的猜测,但我会说常量通常存储在已编译程序的实际CPU指令中,作为立即数据。换句话说,大多数指令都包含用于从中获取数据的地址空间,但如果它是常量,则空间可以保存值本身。
答案 7 :(得分:0)
全局和常量是两个完全分离的关键字。你可以有一个或另一个,没有或两者都有。
然后,您的变量存储在内存中取决于配置。在heap和stack上稍微阅读一下,这将为您提供一些知识,让您了解更多(如果可能,更好,更具体)问题。
答案 8 :(得分:0)
有些常数甚至不存储。
请考虑以下代码:int x = foo(); x *= 2;
。有可能编译器会将乘法转换为x = x+x;
,因为这样可以减少从内存加载数字2的需要。
答案 9 :(得分:0)
可能根本没有存储。
考虑一下这样的代码:
#import<math.h>//import PI
double toRadian(int degree){
return degree*PI*2/360.0;
}
这使程序员能够收集正在发生的事情的想法,但是编译器可以通过在编译时评估常量表达式来优化其中的一些,而大多数编译器都会这样做,这意味着值PI可能不在由此产生的计划。
答案 10 :(得分:0)
正如你所知道的那样,你知道它在链接过程中决定了最终可执行文件的内存布局。还有一个名为COMMON的部分,其中放置了来自不同输入文件的公共符号。这个常见的部分实际上属于.bss部分。
答案 11 :(得分:0)
它必须存储在Text段中,因为它是只读变量。 http://shirleyanengineer.blogspot.in/2017/05/memory-layout-of-process.html
答案 12 :(得分:0)
我检查了x86_64 GNU / Linux系统。通过使用指向“ const”变量的指针,可以更改该值。我用objdump。在文本段中未找到“ const”变量。 'const'变量存储在堆栈中。 “ const”是“ C”中的编译器指令。当编译器遇到更改“ const”变量的语句时,将引发错误。
答案 13 :(得分:0)
答案 14 :(得分:0)