6
#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。

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

4

5 回答 5

11

你很困惑。const和之间没有二分法static;两者是独立的。假设所有数据都已初始化,static const外部(全局)const都将进入,textconst限定static和非const限定外部都将进入data

至于bss,像 ELF 这样的现代二进制格式实际上bss对常量和非常量零数据是分开的。该size命令的输出只是没有显示它。

于 2010-10-17T17:50:19.113 回答
7

来自Kernighan & Ritchie

static 是存储类说明符。其他存储类说明符有:auto、register、extern 和 typedef。static 说明符为声明的对象提供静态存储类。应用于外部变量或函数的静态声明将该对象的范围限制为正在编译的源文件的其余部分。静态对象可能是块的本地对象或所有块的外部,但在任何一种情况下,在退出和重新进入函数和块时都会保留它们的值。

然而,

const 是一个类型限定符。另一个类型限定符是 volatile。const 的目的是宣布可能放置在只读内存中的对象,并可能增加优化的机会。

我想可以推断出这两个关键字都有不同的用途。从它的目的来看,const变量的存在text/code segment是很清楚的。

于 2010-10-17T17:57:14.893 回答
4

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

于 2010-10-17T17:40:21.320 回答
1

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

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

于 2010-10-17T17:52:53.250 回答
1

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

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

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

于 2010-10-17T19:39:33.443 回答