Naw*_*waz 130 c++ program-entry-point standards-compliance entry-point
C++标准中的$ 3.6.1/1节,
程序应包含一个名为main的全局函数,它是程序的指定开始.
现在考虑这段代码,
int square(int i) { return i*i; }
int user_main()
{
for ( int i = 0 ; i < 10 ; ++i )
std::cout << square(i) << endl;
return 0;
}
int main_ret= user_main();
int main()
{
return main_ret;
}
Run Code Online (Sandbox Code Playgroud)
此示例代码执行我打算执行的操作,即在进入main()应该是程序"开始" 的函数之前打印从0到9的整数平方.
我还用-pedantic选项GCC 4.5.0 编译它.它没有错误,甚至没有警告!
所以我的问题是,
这段代码真的符合标准吗?
如果它符合标准,那么它是否会使标准所说的无效?main()不是这个计划的开始!user_main()在执行之前执行main().
我知道要初始化全局变量main_ret,use_main()首先执行,但这是完全不同的事情; 关键是,它确实使标准中的引用语句$ 3.6.1/1无效,因为main()它不是程序的开始 ; 事实上,这个计划已经结束了!
编辑:
它归结为"程序开始"这一短语的定义.那么你究竟如何定义呢?
Ada*_*vis 87
你正在错误地阅读这句话.
程序应包含一个名为main的全局函数,它是程序的指定开始.
该标准是为了标准的其余部分而定义"开始"一词.它并没有说在main调用之前没有代码执行.它说程序的开始被认为是在功能上main.
您的计划符合要求.在main启动之前,您的程序尚未"启动".根据标准中"start"的定义,在程序"启动"之前调用构造函数,但这几乎不重要.代码很多被执行前main被不断调用每一个程序,不只是这个例子.
出于讨论的目的,您的构造函数代码在程序的"开始"之前执行,并且完全符合标准.
Edw*_*uck 83
不,C++在调用main之前做了很多事情来"设置环境"; 但是,main是C++程序中"用户指定"部分的正式启动.
一些环境设置是不可控的(比如设置std :: cout的初始代码;但是,某些环境可以像静态全局块一样控制(用于初始化静态全局变量).注意,因为你没有完整在main之前控制,您无法完全控制静态块初始化的顺序.
在main之后,您的代码在概念上"完全控制"程序,在某种意义上,您既可以指定要执行的指令,也可以指定执行它们的顺序.多线程可以重新排列代码执行顺序; 但是,你仍然可以控制C++,因为你指定让代码段执行(可能)乱序.
Cas*_*Cow 23
除非有主程序,否则您的程序将不会链接,因此不会运行.但是main()不会导致程序执行的开始,因为文件级别的对象具有预先运行的构造函数,并且可以在main()到达之前编写一个运行其生命周期的整个程序,并让main本身具有一个空的身体.
实际上要强制执行此操作,您必须拥有一个在main及其构造函数之前构造的对象来调用程序的所有流程.
看这个:
class Foo
{
public:
Foo();
// other stuff
};
Foo foo;
int main()
{
}
Run Code Online (Sandbox Code Playgroud)
你的程序流程将有效地源于 Foo::Foo()
Rem*_*o.D 15
您也将问题标记为"C",然后,严格地说C,您的初始化应该按照ISO C99标准的第6.7.8节"初始化"失败.
在这种情况下最相关的似乎是约束#4,它说:
具有静态存储持续时间的对象的初始化程序中的所有表达式应为常量表达式或字符串文字.
因此,您的问题的答案是代码不符合C标准.
如果您只对C++标准感兴趣,则可能需要删除"C"标记.
asc*_*ler 10
第3.6节作为一个整体非常清楚main动态初始化的相互作用."程序的指定开始"在其他任何地方都没有使用,只是描述了它的一般意图main().以规范的方式解释一个短语与标准中更详细和明确的要求相矛盾是没有任何意义的.
编译器通常必须在main()之前添加代码以符合标准.因为标准规定必须在程序执行之前完成全局/静态的初始化.如上所述,对于放置在文件范围(全局)的对象的构造函数也是如此.
因此,原始问题也与C相关,因为在C程序中,您仍然可以在程序启动之前执行全局/静态初始化.
标准假设这些变量是通过"魔术"初始化的,因为它们没有说明在程序初始化之前应该如何设置它们.我认为他们认为这是一种超出编程语言标准范围的东西.
编辑:参见例如ISO 9899:1999 5.1.2:
具有静态存储持续时间的所有对象应在程序启动之前初始化(设置为其初始值).否则,未指定这种初始化的方式和时间.
关于如何完成这种"神奇"的理论可以追溯到C的诞生,当时它是一种仅用于UNIX OS的编程语言,基于RAM的计算机.从理论上讲,程序将能够将所有预先初始化的数据从可执行文件加载到RAM中,同时程序本身被上传到RAM.
从那时起,计算机和操作系统已经发展,并且C用于比原先预期的更广泛的区域.现代PC OS具有虚拟地址等,并且所有嵌入式系统都从ROM而不是RAM执行代码.因此,有许多情况下RAM无法"自动"设置.
此外,标准过于抽象,无法了解堆栈和进程内存等.在程序启动之前,这些事情也必须完成.
因此,几乎每个C/C++程序都有一些在调用main之前执行的init /"copy-down"代码,以符合标准的初始化规则.
例如,嵌入式系统通常有一个称为"非ISO兼容启动"的选项,其中出于性能原因跳过整个初始化阶段,然后代码实际上直接从main启动.但是这样的系统不符合标准,因为你不能依赖全局/静态变量的init值.
| 归档时间: |
|
| 查看次数: |
19874 次 |
| 最近记录: |