Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中的常量变量存储在哪里?_C_Variables_Memory Management_Constants_Globals - Fatal编程技术网

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

C中的常量变量存储在哪里?,c,variables,memory-management,constants,globals,C,Variables,Memory Management,Constants,Globals,我想知道常量变量存储在哪里。它是否与全局变量位于同一内存区域?还是在堆栈上?它们的存储方式是一个实现细节(取决于编译器) 例如,在GCC编译器中,在大多数机器上,只读变量、常量和跳转表都放在文本部分。通常它们存储在只读数据部分(而全局变量部分具有写入权限)。所以,试图通过获取常数的地址来修改常数可能会导致访问冲突 但这实际上取决于您的硬件、操作系统和编译器。这主要是一个有根据的猜测,但我要说的是,常量通常作为即时数据存储在编译程序的实际CPU指令中。因此,换句话说,大多数指令都包含用于从中获取数

我想知道常量变量存储在哪里。它是否与全局变量位于同一内存区域?还是在堆栈上?

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


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

通常它们存储在只读数据部分(而全局变量部分具有写入权限)。所以,试图通过获取常数的地址来修改常数可能会导致访问冲突


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

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

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


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

全局和常量是两个完全分开的关键字。你可以有一个或另一个,没有或两者都有

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

考虑一下代码:

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”部分(通常分配零变量)或“数据”部分(通常分配初始化变量)

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


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

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


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

一些常量甚至没有存储

考虑以下代码:

intx=foo();
x*=2;

编译器可能会将乘法转换为
x=x+x这样可以减少从内存中加载数字2的需要。

它可能根本不会被存储

考虑以下代码:

#import<math.h>//import PI
double toRadian(int degree){
  return degree*PI*2/360.0;
}
#导入//导入PI
双环面(整数度){
返回度*PI*2/360.0;
}

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

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

  • 代码段-仅存储代码、ROM
  • BSS(或由符号启动的块)数据段-存储初始化的全局变量和静态变量
  • 堆栈段-存储所有局部变量和有关函数返回地址等的其他信息
  • 堆段-所有动态分配都发生在这里
  • 数据BSS(或以符号开头的块)段-存储未初始化的全局变量和静态变量
  • 请注意,数据段和BSS段之间的区别在于前者存储初始化的全局变量和静态变量,而后者存储未初始化的变量

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

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

    例如:

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

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

    当然不是,因为

    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字节且相等