C++ 将 'main' 声明为对函数的引用?
C++ declare 'main' as a reference to function?
如果我将 main 定义为对函数的引用会怎样?
#include<iostream>
#include<cstring>
using namespace std;
int main1()
{
cout << "Hello World from main1 function!" << endl;
return 0;
}
int (&main)() = main1;
会发生什么?我在在线编译器中测试时出现错误 "Segmentation fault":
在 VC++ 2013 下,它会创建一个在 运行 时崩溃的程序!
调用函数指针数据的代码将被编译为代码,这将在启动时立即崩溃。
我还想要一个关于此的 ISO C++ 标准引用。
如果你想根据这样的宏定义 2 个入口点中的任何一个,这个概念将很有用:
int main1();
int main2();
#ifdef _0_ENTRY
int (&main)() = main1;
#else
int (&main)() = main2;
#endif
这不是一个符合标准的 C++ 程序。 C++ 要求(第 3.6.1 节)
A program shall contain a global function called main
您的程序包含一个名为 main
的全局非函数,它与所需的 main
函数发生名称冲突。
这样做的一个理由是它允许托管环境在程序启动期间对 main
进行函数调用。它不等同于源字符串 main(args)
,后者可能是函数调用、函数指针取消引用、在函数对象上使用 operator()
或类型实例的构造 main
.不,main
必须是函数。
另一件需要注意的事情是 C++ 标准从不说明 main
的类型实际上是什么,并且阻止您观察它。因此,实现可以(并且确实!)重写签名,例如添加您省略的 int argc, char** argv, char** envp
中的任何一个。显然它不知道为您的 main1
和 main2
.
执行此操作
This would be useful if you want to define either of 2 entry-points depending on some macro
不,不是真的。你应该这样做:
int main1();
int main2();
#ifdef _0_ENTRY
int main() { return main1(); }
#else
int main() { return main2(); }
#endif
由于 CWG issue 1886 的决议,目前处于 "tentatively ready" 状态,这很快就会变得明显不正确,它在 [[=17] 中添加了以下内容=]]:
A program that declares a variable main
at global scope or that
declares the name main
with C language linkage (in any namespace) is
ill-formed.
实践中会发生什么在很大程度上取决于实施。
在您的情况下,您的编译器显然将该引用实现为 "pointer in disguise"。除此之外,指针还有外部链接。 IE。您的程序导出一个名为 main
的外部符号,它实际上与指针占用的数据段中的内存位置相关联。链接器没有过多地查看它,而是将该内存位置记录为程序的入口点。
稍后,尝试将该位置用作入口点会导致分段错误。首先,该位置没有有意义的代码。其次,仅仅尝试将控制权传递到数据段内的某个位置可能会触发平台的 "data execution protection" 机制。
通过这样做,您显然希望引用得到优化,即 main
将成为 main1
的另一个名称。在你的情况下,它没有发生。引用作为独立的外部对象幸存下来。
看来您已经回答了关于发生了什么的问题。
至于为什么,在您的代码中 main
是函数的 reference/pointer。这与函数不同。如果代码调用的是指针而不是函数,我预计会出现段错误。
如果我将 main 定义为对函数的引用会怎样?
#include<iostream>
#include<cstring>
using namespace std;
int main1()
{
cout << "Hello World from main1 function!" << endl;
return 0;
}
int (&main)() = main1;
会发生什么?我在在线编译器中测试时出现错误 "Segmentation fault":
在 VC++ 2013 下,它会创建一个在 运行 时崩溃的程序!
调用函数指针数据的代码将被编译为代码,这将在启动时立即崩溃。
我还想要一个关于此的 ISO C++ 标准引用。
如果你想根据这样的宏定义 2 个入口点中的任何一个,这个概念将很有用:
int main1();
int main2();
#ifdef _0_ENTRY
int (&main)() = main1;
#else
int (&main)() = main2;
#endif
这不是一个符合标准的 C++ 程序。 C++ 要求(第 3.6.1 节)
A program shall contain a global function called
main
您的程序包含一个名为 main
的全局非函数,它与所需的 main
函数发生名称冲突。
这样做的一个理由是它允许托管环境在程序启动期间对 main
进行函数调用。它不等同于源字符串 main(args)
,后者可能是函数调用、函数指针取消引用、在函数对象上使用 operator()
或类型实例的构造 main
.不,main
必须是函数。
另一件需要注意的事情是 C++ 标准从不说明 main
的类型实际上是什么,并且阻止您观察它。因此,实现可以(并且确实!)重写签名,例如添加您省略的 int argc, char** argv, char** envp
中的任何一个。显然它不知道为您的 main1
和 main2
.
This would be useful if you want to define either of 2 entry-points depending on some macro
不,不是真的。你应该这样做:
int main1();
int main2();
#ifdef _0_ENTRY
int main() { return main1(); }
#else
int main() { return main2(); }
#endif
由于 CWG issue 1886 的决议,目前处于 "tentatively ready" 状态,这很快就会变得明显不正确,它在 [[=17] 中添加了以下内容=]]:
A program that declares a variable
main
at global scope or that declares the namemain
with C language linkage (in any namespace) is ill-formed.
实践中会发生什么在很大程度上取决于实施。
在您的情况下,您的编译器显然将该引用实现为 "pointer in disguise"。除此之外,指针还有外部链接。 IE。您的程序导出一个名为 main
的外部符号,它实际上与指针占用的数据段中的内存位置相关联。链接器没有过多地查看它,而是将该内存位置记录为程序的入口点。
稍后,尝试将该位置用作入口点会导致分段错误。首先,该位置没有有意义的代码。其次,仅仅尝试将控制权传递到数据段内的某个位置可能会触发平台的 "data execution protection" 机制。
通过这样做,您显然希望引用得到优化,即 main
将成为 main1
的另一个名称。在你的情况下,它没有发生。引用作为独立的外部对象幸存下来。
看来您已经回答了关于发生了什么的问题。
至于为什么,在您的代码中 main
是函数的 reference/pointer。这与函数不同。如果代码调用的是指针而不是函数,我预计会出现段错误。