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

发布于 2024-08-07 11:23:07 字数 43 浏览 9 评论 0原文

我想知道常量变量存储在哪里。和全局变量在同一个内存区吗?或者它在堆栈上?

I wonder where constant variables are stored. Is it in the same memory area as global variables? Or is it on the stack?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

初见你 2024-08-14 11:23:07

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

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

How they are stored is an implementation detail (depends on the compiler).

For example, in the GCC compiler, on most machines, read-only variables, constants, and jump tables are placed in the text section.

等风也等你 2024-08-14 11:23:07

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

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

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

现在,为什么我要谈论数据分段,而我必须只是告诉常量变量存储在哪里......这是有原因的......

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

例如:

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

总而言之,“const”只是一个数据限定符,这意味着首先编译器必须决定变量必须存储在哪个段中,然后如果变量是 const,则它有资格存储在该特定段的写保护区域中。

Depending on the data segmentation that a particular processor follows, we have five segments:

  1. Code Segment - Stores only code, ROM
  2. BSS (or Block Started by Symbol) Data segment - Stores initialised global and static variables
  3. Stack segment - stores all the local variables and other informations regarding function return address etc
  4. Heap segment - all dynamic allocations happens here
  5. Data BSS (or Block Started by Symbol) segment - stores uninitialised global and static variables

Note that the difference between the data and BSS segments is that the former stores initialized global and static variables and the later stores UNinitialised ones.

Now, Why am I talking about the data segmentation when I must be just telling where are the constant variables stored... there's a reason to it...

Every segment has a write protected region where all the constants are stored.

For example:

  • If I have a const int which is local variable, then it is stored in the write protected region of stack segment.
  • If I have a global that is initialised const var, then it is stored in the data segment.
  • If I have an uninitialised const var, then it is stored in the BSS segment...

To summarize, "const" is just a data QUALIFIER, which means that first the compiler has to decide which segment the variable has to be stored and then if the variable is a const, then it qualifies to be stored in the write protected region of that particular segment.

愿得七秒忆 2024-08-14 11:23:07

考虑一下代码:

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 未使用(可能是因为它是单个文件的本地文件),则它可能根本不会出现在目标代码中。如果引用 k 的对 totherfunc() 的调用没有被注释掉,那么 k 必须在某处分配一个地址 - 它很可能与 i 位于同一段。

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

请注意,我强制变量之所以出现,是因为我通过引用传递了它们 - 大概是传递给一个需要指向常量整数的指针的函数。如果地址从未被占用,则可以从代码中完全优化 jk。要删除i,编译器必须知道整个程序的所有源代码 - 它可以在其他翻译单元(源文件)中访问,因此不能轻易删除。如果程序沉迷于动态加载共享库,那么情况就更糟了——这些库之一可能依赖于该全局变量。

(风格上 - 变量 ij 应该有更长、更有意义的名称;这只是一个例子!)

Consider the code:

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);
}

Generally, i can be stored in the text segment (it's a read-only variable with a fixed value). If it is not in the text segment, it will be stored beside the global variables. Given that it is initialized to zero, it might be in the 'bss' section (where zeroed variables are usually allocated) or in the 'data' section (where initialized variables are usually allocated).

If the compiler is convinced the k is unused (which it could be since it is local to a single file), it might not appear in the object code at all. If the call to totherfunc() that references k was not commented out, then k would have to be allocated an address somewhere - it would likely be in the same segment as i.

The constant (if it is a constant, is it still a variable?) j will most probably appear on the stack of a conventional C implementation. (If you were asking in the comp.std.c news group, someone would mention that the standard doesn't say that automatic variables appear on the stack; fortunately, SO isn't comp.std.c!)

Note that I forced the variables to appear because I passed them by reference - presumably to a function expecting a pointer to a constant integer. If the addresses were never taken, then j and k could be optimized out of the code altogether. To remove i, the compiler would have to know all the source code for the entire program - it is accessible in other translation units (source files), and so cannot as readily be removed. Doubly not if the program indulges in dynamic loading of shared libraries - one of those libraries might rely on that global variable.

(Stylistically - the variables i and j should have longer, more meaningful names; this is only an example!)

谁人与我共长歌 2024-08-14 11:23:07

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

gcc 放置只读常量.text 部分,除非另有说明。

Depends on your compiler, your system capabilities, your configuration while compiling.

gcc puts read-only constants on the .text section, unless instructed otherwise.

自控 2024-08-14 11:23:07

通常它们存储在只读数据部分(而全局变量部分具有写权限)。因此,尝试通过获取常量的地址来修改常量可能会导致访问冲突,也称为段错误。

但这实际上取决于您的硬件、操作系统和编译器。

Usually they are stored in read-only data section (while global variables' section has write permissions). So, trying to modify constant by taking its address may result in access violation aka segfault.

But it depends on your hardware, OS and compiler really.

摇划花蜜的午后 2024-08-14 11:23:07

当然不是,因为

1) bss 段存储了非 inilized 变量,显然还有另一种类型。

       (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 个字节且值相等。

但我怀疑局部常数会在哪里?

offcourse not , because

1) bss segment stored non inilized variables it obviously another type is there.

       (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) data segment is initlaized variables it has 3 types ,

      (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.

i mention above small and large means depents upon complier for example small means < than 8 bytes and large means > than 8 bytes and equal values.

but my doubt is local constant are where it will stroe??????

过期情话 2024-08-14 11:23:07

这主要是一个有根据的猜测,但我想说的是,常量通常作为即时数据存储在编译程序的实际 CPU 指令中。换句话说,大多数指令都包含用于从中获取数据的地址的空间,但如果它是常量,则该空间可以保存值本身。

This is mostly an educated guess, but I'd say that constants are usually stored in the actual CPU instructions of your compiled program, as immediate data. So in other words, most instructions include space for the address to get data from, but if it's a constant, the space can hold the value itself.

眉黛浅 2024-08-14 11:23:07

这是 Win32 系统特有的。

输入图片此处描述

This is specific to Win32 systems.

enter image description here

破晓 2024-08-14 11:23:07

它依赖于编译器,但请注意,它甚至可能没有完全存储。因为编译器只需要优化它并将其值直接添加到使用它的表达式中。

我将此代码添加到程序中,并使用 gcc for arm cortex m4 进行编译,检查内存使用情况的差异。

没有const

int someConst[1000] = {0};

在此处输入图像描述

使用 const

const int someConst[1000] = {0};

在此处输入图像描述

It's compiler dependence but please aware that it may not be even fully stored. Since the compiler just needs to optimize it and adds the value of it directly into the expression that uses it.

I add this code in a program and compile with gcc for arm cortex m4, check the difference in the memory usage.

Without const:

int someConst[1000] = {0};

enter image description here

With const:

const int someConst[1000] = {0};

enter image description here

橘寄 2024-08-14 11:23:07

Global 和 Constant 是两个完全分开的关键字。您可以选择其中之一,也可以不选择或两者兼而有之。

那么,变量在内存中的存储位置取决于配置。阅读一些关于stack,这将为您提供一些知识来提出更多(如果可以的话,更好、更具体)的问题。

Global and constant are two completely separated keywords. You can have one or the other, none or both.

Where your variable, then, is stored in memory depends on the configuration. Read up a bit on the heap and the stack, that will give you some knowledge to ask more (and if I may, better and more specific) questions.

夏至、离别 2024-08-14 11:23:07

它可能根本不被存储。

考虑这样的一些代码:

#import<math.h>//import PI
double toRadian(int degree){
  return degree*PI*2/360.0;
}

这使程序员能够收集正在发生的事情的想法,但是编译器可以通过在编译时评估常量表达式来优化其中一些,并且大多数编译器都会这样做,这意味着值 PI 可能会根本不在最终的程序中。

It may not be stored at all.

Consider some code like this:

#import<math.h>//import PI
double toRadian(int degree){
  return degree*PI*2/360.0;
}

This enables the programmer to gather the idea of what is going on, but the compiler can optimize away some of that, and most compilers do, by evaluating constant expressions at compile time, which means that the value PI may not be in the resulting program at all.

平安喜乐 2024-08-14 11:23:07

就像一个附加组件一样,正如您所知,它在链接过程中决定了最终可执行文件的内存布局。还有一个称为 COMMON 的部分,其中放置来自不同输入文件的公共符号。这个公共部分实际上属于在 .bss 部分下。

Just as an an add on ,as you know that its during linking process the memory lay out of the final executable is decided .There is one more section called COMMON at which the common symbols from different input files are placed.This common section actually falls under the .bss section.

蓝戈者 2024-08-14 11:23:07

有些常量甚至没有被存储。

考虑以下代码:

int x = foo();
x *= 2;

编译器很可能会将乘法转换为 x = x+x; ,因为这减少了从内存加载数字 2 的需要。

Some constants aren't even stored.

Consider the following code:

int x = foo();
x *= 2;

Chances are that the compiler will turn the multiplication into x = x+x; as that reduces the need to load the number 2 from memory.

雪化雨蝶 2024-08-14 11:23:07

我检查了 x86_64 GNU/Linux 系统。通过取消引用指向“const”变量的指针,可以更改该值。我用的是objdump。在文本段中找不到“const”变量。 “const”变量存储在堆栈中。
'const' 是“C”中的编译器指令。当编译器遇到更改“const”变量的语句时,编译器会抛出错误。

I checked on x86_64 GNU/Linux system. By dereferencing the pointer to 'const' variable, the value can be changed. I used objdump. Didn't find 'const' variable in text segment. 'const' variable is stored on stack.
'const' is a compiler directive in "C". The compiler throws error when it comes across a statement changing 'const' variable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文