我在阅读C ++常见问题解答,但发现一句话。
main()不能内联。
为什么是这样?
我在阅读C ++常见问题解答,但发现一句话。
main()不能内联。
为什么是这样?
main
函数编译到其中。答案是,因为您无法重新编译操作系统?
inline
(请记住,这只是一个提示!)。
Answers:
在C ++中,在代码中调用main函数是不合法的,因此不可能内联。
*static_cast<int*>(0) = 10
编译,这并不意味着它是正确的...就像任何ODR违规以及许多其他事情一样...它可以编译的事实并不意味着它是一个合法程序。
因为该标准是这样说的:
[2003: 3.6.1/3]
:在程序中不得使用main函数(3.2)。main的链接(3.5)是实现定义的。声明main为嵌入式或静态的程序格式错误。名称main否则不保留。[示例:成员函数,类和枚举可以称为main,其他命名空间中的实体也可以称为main。]
为什么这么说呢?因为它试图将更多的实现留给main
个人来做,所以,实现是尽可能的,并且不想通过inline
在可能没有实际好处的情况下要求此处有效来限制实现。
我在委员会上的朋友证实了这一点:
inline
main()
本身没有任何理由不起作用。[..]我可能有一个C ++解释器,可以调用inlinedmain()
。[..] [但是]inline
/static
main()
是被禁止的,以期避免混乱。我很难想象,该原理将是在[此问与答]中已经说过的东西之外的任何东西。
顺便说一句,不要将inline
hint关键字与实际的内联函数混淆。您可以标记一个函数inline
,但实际上可能没有内联。
因此,即使main
“不能内联”的确是正确的(严格地说,这是不正确的,尽管内联会main
很笨拙且毫无意义,如其他答案所述),但理论上它仍inline
可以很好地支持提示关键字。
这不是出于上述原因,而是在litb的回答中:它会使事情变得复杂,没有任何实际好处。
inline
的main
是平凡的,因为它正好可以忽略不计,因此,不限制任何实现的,因此,这可能的原因为标准的禁令是站不住脚的。抱歉。但是我提供的无非是我的回答,那就是没有任何意义inline
(对此,我们认为我认为是正确的)。
main
在多个TU中进行定义,如果这些定义在词法上都是相同的(除其他限制之外),那么意义不大,值得禁止。
main
它的含义必须与实现的运行时以及与主机操作系统进行交互(因为它是程序的入口点),因此,由人组成的委员会对其进行过多的授权是没有意义的。回想一下,其他功能键联是用户自定义等,其实,标准是制约main
略有这里,说:“听你的编译器供应商,因为他们开始选择这个不是你”。:)
C运行时库需要找到该符号,以便“知道”要运行的功能。
call
对该main()
函数的显式显示,并且几乎总是动态链接。因此,在典型情况下,它根本无法工作。
通常main()
从系统init()
函数中调用。因此,需要为定义一个准确的定义main()
。
现在,如果我们可以使用inline
该main()
函数并将其包含在头文件中,那么对于每个翻译单元,都会有不同的定义main()
。这是不允许的。您可以main()
在namespace
和中声明inline
。但不是全球性的main()
。
inline
。
static int main()
格式不正确的原因:D)
static int main()
等价于namespace { int main() }
。我已经在答案中提到了。
main
函数的多个实例,那么您的意思是什么?
首先,您必须了解内联工作的功能
例:
inline void f() {
int a = 3;
a += 3;
cout << a;
}
int main() {
f();
return 0;
}
在编译器中看起来像:
int main() {
int a = 3;
a += 3;
cout << a;
return 0;
}
看这个例子,你想如何使主内联?此方法立即内联。
inline
仅具有一次调用的d函数和仅具有一次调用的main
函数之间有什么区别?
This method is inline immediately.
不对。inline
仅是一个提示。它不执行功能内联。
C ++标准表示main
,根据@Tomalak Geret'kal的回复,不能内联该函数。该响应讨论main
了删除标准中的限制时内联函数的可能性。
内联
的定义inline
关键字是对编译器的建议,可将其内容原位粘贴。一种目的是消除存在于从函数(子例程)调用和返回中的开销。
内联的重要情况是存在指向函数的指针的情况。在这种情况下,必须至少有一个该功能的静态副本。在这种情况下,链接器可以解析内联函数的“外部链接”,因为存在一个静态版本。
重要的是要注意,编译器和链接器确定是粘贴内容还是调用函数的单个实例。
还要注意的是,编译器也可以内联未编程人员未标记的功能。
内联主要功能
由于仅main
允许一次调用,因此如何链接取决于编译器。标准允许内联函数的单个实例。允许编译器将inlined
函数转换为对单个实例的函数调用。因此,编译器将忽略对该main
函数的内联建议。
编译器和链接器必须确保仅main
存在一个内联函数的实例。这是棘手的部分出现的地方,尤其是在外部链接中。确保一个实例的一种过程是让翻译具有“主”功能(无论是否内联)。 注意:调用内联函数时,允许编译器从符号表中删除该函数以进行外部链接,因为这样的想法是外部函数不会调用该函数。
总结
从技术上讲,没有什么可以阻止该main
函数被内联的。的机械已存在用于将内联的函数成单实例和用于识别功能的多个实例。当存在指向内联函数的指针时,将创建一个函数的单个实例,因此它具有一个地址。该机器将满足运行时库对main
具有地址的要求。在inline
formain
函数的情况下,它将被忽略,但不应有任何理由阻止这种语法(除非使人感到困惑)。毕竟,已经有多余的语法案例,例如将通过值(副本)传递的参数声明为const
。
“那只是我的看法,我可能是错的。” -喜剧演员丹尼斯·米勒(Dennis Miller)。
其他人指出,main
在机器代码级别上不能有意义地内联的调用。那是垃圾 这将需要链接程序提供一些帮助(例如全局优化),或者需要按应用程序重新编译运行时库的一部分,但这是完全可行的,这里没有技术问题。
但是,调用的提示效果inline
最好应该是内联的,与仅在控件的最高级别被调用一次的函数无关main
。
唯一保证效果的inline
是,以允许在两个或多个翻译单元(相同)中所定义的外部联动功能,即影响了一个定义规则。
实际上,这允许将定义放置在头文件中,并且将其放置在头文件中实际上也是保证相同定义的必要条件。
这不会使意义main
,所以没有理由main
要inline
。
main
要inline
”是迫不得已的,但不是直接的解释,为什么它已经取得使其不能被标记inline
。
main
并不完美。例如,我一直认为并且仍然认为“ main的第一个语句之后”位从根本上是错误的。但是我从未见过任何地方讨论它。也许,这只是我对英语的不完全理解...
您只能定义main
一次。因此,放置inline
将无济于事-inline
仅对您可以在程序中多次定义的功能有重要意义(所有定义都将被视为只有一个定义,并且所有定义必须相同)。
因为inline
可以在程序中多次定义函数,并且inline
还具有inline
尽可能快地调用带标记的函数的目的,所以该标准要求inline
在使用该函数的每个翻译单元中都定义函数。因此,如果inline
当前翻译单元中的代码未使用该函数的定义并且该函数未使用该函数,则编译器通常会放弃该函数的定义。这样做main
完全是错误的,这表明inline
语义与语义main
完全不兼容。
请注意,标题中的问题“为什么不能内联C ++中的main()?” 您引用的标准声明涉及的是不同的内容。您正在询问该函数是否可以内联,这通常被理解为将被调用函数的代码完全或部分插入到调用函数中。仅标记一个函数inline
并不意味着完全内联该函数。这完全是编译器的决定,当然,如果您从不调用main
(并且您不能这样做),则没有任何内容可以内联。
main
内联将需要它。从历史上看,C ++不喜欢要求魔术。(但这是在模板之前。)
我看到该标准是这样说的,但是真正的实际答案将很简单,就像声明添加到每个C和C ++程序的运行时必须调用可执行文件中的某个点一样。该函数应该有一个外部符号(运行时带有地址),以便链接程序可以在执行开始时找到要调用的函数。因此,您不能将其声明为inline
,因为内联的编译器不会为其生成外部符号。
inline
并不一定导致该功能内联。
inline
函数有extern链接,除非它是一个的显式声明的一个命名空间范围功能static
。
对于大多数编译器/体系结构组合,main()
源代码中的函数在最终二进制文件中成为合理的正常函数。这仅是因为在这些架构上很方便,而不是因为标准规定必须如此。
在受内存限制的体系结构上,许多编译器会生成平坦的二进制文件(如intex十六进制格式),而不是动态链接程序友好的容器(如elf或xcoff),它们会优化所有样板,因为这样做只会肿。有些体系结构根本不支持函数调用(在这些平台上只能使用C ++的有限子集。)
为了支持最广泛的此类架构和构建环境,该标准选择保留以下内容的语义: main()
尽可能开放,以便编译器可以为最广泛的平台做正确的事。这意味着从整体上来说,该语言中的许多功能都无法应用于应用程序本身的启动和关闭。
如果您需要内联main()
(或可重入,或任何精美的功能)之类的东西,您当然可以调用main函数:
inline int myMain(int argc, char **argv) { /* whatever */ }
int main(int argc, char **argv) { return myMain(argc, argv); }
操作系统将二进制数据加载到内存中;寻找入口点(c / c ++中的“主要”符号);跳至入口点标签的地址。在未加载程序之前,操作系统对代码中的主要功能一无所知。
main
。而是,OS调用程序的机器代码级别入口点。对于C和C ++,该入口点通常是运行时库中的一个函数,它依次执行各种初始化工作,然后调用main
,最后清理(例如,调用已安装的退出处理程序)并退出。