C语言 为什么const int main = 195导致一个工作程序,但没有const,它以分段错误结束



考虑以下C程序(参见这里的实时演示)。

const int main = 195;

我知道在现实世界中没有程序员写这样的代码,因为它没有任何有用的目的,没有任何意义。但是,当我从上面的程序中删除const关键字时,它立即导致分割错误。为什么?我很想知道这背后的原因。

GCC 4.8.2在编译时给出如下警告:

警告:'main'通常是一个函数[-Wmain]

const int main = 195;
          ^

为什么const关键字的存在和不存在会对程序的行为产生影响?

观察值195如何对应于8086兼容设备上的ret(从函数返回)指令。因此,main的定义在执行时的行为就像您将其定义为int main() {}一样。

在某些平台上,const数据被加载到可执行但不可写的内存区域,而可变数据(即不符合const的数据)被加载到可写但不可执行的内存区域。由于这个原因,当您将main声明为const时,程序"工作",但当您放弃const限定符时,程序就不工作了。

传统上,二进制文件包含三个段:

  • text段(如果体系结构支持)是写保护的,可执行的,包含可执行代码,静态存储持续时间合格的const变量和字符串字量
  • data段是可写的,不能执行。它包含不具有静态存储持续时间的const变量和(在运行时)具有分配存储持续时间
  • 的对象。
  • bss段与data段相似,但初始化为全零。它包含静态存储持续时间不符合const的变量,这些变量在没有初始化式
  • 的情况下声明。
  • stack段不存在于二进制文件中,并且包含具有自动存储持续时间
  • 的变量

从变量main中删除const限定符会导致它从text段移动到data段,这是不可执行的,导致您观察到的分段冲突。

现代平台通常有进一步的段(例如,rodata段用于既不可写也不可执行的数据),所以在没有参考平台特定文档的情况下,请不要将其视为对平台的准确描述。

请理解,不将main作为函数通常是不正确的,尽管从技术上讲,平台可以允许将main声明为变量,参见ISO 9899:2011§5.1.2.2.1¶1,强调我:

1程序启动时调用的函数命名为main。实现没有为这个函数声明原型。它应该定义为返回类型int,不带参数(…),或者带两个参数(…),或者是等价的;或者以其他实现定义的方式

在C语言中,main在全局作用域中几乎总是一个函数。

在全局作用域中使用main作为变量会使程序的行为未定义。

(它只是可能是这样的情况,当您编写const时,编译器将变量优化为常量,因此您的程序行为不同。但是程序行为是仍然 undefined)。

最新更新