2010-10-17 69 views
5
#include <stdio.h> 

const int str[1000] = {0}; 

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

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

[-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为“静态”。

该变量是全局变量,应该可以从它所属的可执行文件中的任何地方访问(因为没有“静态”),但给定了变量,我不知道它为什么放在文本段而不是数据中分割?

+0

+1:好问题。你可能想把它扩展到'static const'。 – Arun 2010-10-17 17:49:27

回答

6

你很困惑。在conststatic之间没有二分法;这两个是独立的。假设所有数据都已初始化,则static const和外部(全局)const将进入text,并且非const合格的static和非const合格的外部将进入data

至于bss,像ELF这样的现代二进制格式对于恒定和非恒定的零数据实际上有单独的bsssize命令的输出只是不显示它。

+0

你说得对。感谢您的澄清。 – helpmelearn 2010-10-17 18:25:42

3

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

1

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

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

7

Kernighan的&里奇

静是一个存储类说明。 其他存储类别说明符是: auto,register,extern & typedef。静态指定符为 对象提供静态存储类。应用于外部变量或函数的静态声明将该对象的范围限制为正在编译的源文件的其余部分。静态 对象可能位于所有块外部的块或 ,但在 大小写保留其值从整个出口 开始并重新进入功能块和 块。

然而,

const为类型限定符。其他 类型限定符是易失性的。 const的目的是宣布 可能被放置在 只读内存中的对象,也许 增加优化 的机会。

我想可以推断出这两个关键字有不同的目的; const的变量在text/code segment中的变量与其目的相当明显。

+2

+1用于引用K&R – 2010-10-17 18:06:12

1

通过将常量数据放入文本部分,编译器试图强制执行常量。

请记住,TEXT部分已加载到标记为只读在MMU页表中的内存页中。这是为了防止代码的意外损坏。通过将常量数据放入同一区域,使该数据只读。对这些数据的任何写入都会调用异常。

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