声明为“const”的全局初始化变量转到文本段,而声明为“Static”的全局初始化变量转到数据段。为什么?

时间:2010-10-17 17:33:56

标签: c static elf

#include <stdio.h>

const int str[1000] = {0};

int main(void)
{
    printf("arr is %d\n", str[0]);
    return 0;
}

具有以下输出:

[-exercises/adam/stack2]:size a.out
   text    data     bss     dec     hex filename
   5133     272      24    5429    1535 a.out

鉴于:

#include <stdio.h>

static int str[1000] = {0};

int main(void)
{
    printf("arr is %d\n", str[0]);
    return 0;
}

具有以下输出:

[-exercises/adam/stack2]:size a.out
   text    data     bss     dec     hex filename
   1080    4292      24    5396    1514 a.out

当数组未初始化时 - 它再次进入“const”的文本段和“静态”的BSS。

变量是全局变量,应该可以从可执行文件中的任何位置访问(因为没有“静态”),但是如果它是变量,我不知道它为什么放在文本段而不是数据段中?

5 个答案:

答案 0 :(得分:7)

来自 Kernighan&amp;里奇

  

static是存储类说明符。   其他存储类说明符是:   auto,register,extern&amp;的typedef。该   static specifier给出声明的   对象静态存储类。应用于外部变量或函数的静态声明将该对象的范围限制为正在编译的源文件的其余部分。静态的   对象可以是块的本地对象   所有街区外部,但在其中一个   案例在退出时保留其值   从和重新进入功能和   块。

然而,

  

const是一个类型限定符。另一个   type限定符是volatile。该   const的目的是宣布   可放入的物体   只读内存,也许是   增加机会   优化

我想可以推断这两个关键字都有不同的用途; const中的text/code segment个变量的目的非常明确。

答案 1 :(得分:6)

你很困惑。 conststatic之间没有二分法;两者是独立的。假设所有数据都已初始化,static const和外部(全局)const都会进入text,而非const - 合格static和非{ {1}} - 符合条件的外部版本将进入const

对于data,像ELF这样的现代二进制格式实际上对于常量和非常量零数据具有单独的bssbss命令的输出只是没有显示它。

答案 2 :(得分:3)

允许内存保护工作。任何写入const的尝试都会触发段错误。

答案 3 :(得分:1)

当你声明一个变量const时,你告诉编译器你永远不打算改变它的值。另一方面,使用在文件范围内进行的static声明,您告诉编译器该变量对于已声明的编译单元是私有的,但仍允许该编译单元中的函数修改此变量。

正如Oli在answer中提到的那样,在const段中找到text变量可以让系统强制执行内存访问保护。此外,考虑一个嵌入式系统,在这种情况下,text段通常写入闪存,因此是不可修改的。 databss段等位于RAM中,允许修改。

答案 4 :(得分:1)

通过将const数据放入文本部分,编译器正在尝试强制执行const。

请记住,TEXT部分被加载到MMU页面表中标记为只读的内存页面中。这是为了防止代码意外损坏。通过将const数据放在同一区域中,也可以只读取该数据。然后,对此数据的任何写入都将调用异常。

声明为static的未初始化数据将进入BSS段以节省可执行文件中的空间。该区域由加载器分配在内存中。声明为static的初始化数据将进入DATA段,这是可读写的。