C语言必须从main函数开始执行吗?

**

C语言必须从main函数开始执行吗?

**

前言

在C语言中main函数,是程序的入口,是程序的开始,也是在main函数结束。

引出问题,C语言程序必须从main函数开始吗?

回答:当然是否定的。

在C primer plus 书中是这样解释的:C程序一定是从main()函数开始执行(目前不包括特殊情况)

也就是说,C程序不一定是从main()函数开始,

下面来探讨一下,这个问题。

我查阅了一些资料,才弄清楚这个问题:


从汇编语言的角度,我们可以发现程序的入口地址是可以指定的,C语言编译器默认给我们程序指定的入口地址为main()函数地址

通过查阅的资料,发现不同的编译器指定函数的入口地址的方式不一样

简介attribute关键字

attribute可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute)等.

attribute 书写特征是:attribute 前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的__attribute__ 参数。

attribute 语法格式为:attribute ((constructor)) void before_main();

constructor属性设置函数在所有函数之前执行.

destructor设置函数在所有函数退出后执行。

FUNCTION,_FILE_和_LINE_定位程序运行时的错误。程序预编译时预编译器将用所在的函数名,文件名和行号替换。当运行时错误产生后这三个宏分别能返回错误所在的函数,所在的文件名和所在的行号。

在gcc中,我们可以使用attribute关键字,声明constructor和destructor,进行指定函数的入口地址。

代码如下:

#include<stdio.h>

__attribute((constructor)) void before_main(void)
{
    
    
	printf("调用main()之前调用的函数\n");
	printf("%s\n",__FUNCTION__);
}

__attribute((destructor)) void after_main(void)
{
    
    
	printf("调用main()之后调用的函数\n");
	printf("%s\n",__FUNCTION__);
}
int main(int argc,char **argv)
{
    
    
	printf("调用main()函数\n");
	printf("%s\n",__FUNCTION__);
	return 0;
}

程序运行的结果如下:

调用main()之前调用的函数
before_main
调用main()函数
main
调用main()之后调用的函数
after_main

上述的方法适用于gcc环境中,VS不支持attribute关键字,但是在VS中也可以指定函数入口地址,方法和代码如下:

#include <stdio.h>
int
main( int argc, char ** argv)
{
    
    
	printf("调用main()函数\n");
    printf("%s\n",__FUNCTION__);
    return 0;
}

int before_main(void)
{
    
    
	printf("调用main()之前调用的函数\n");
    printf("%s\n",__FUNCTION__);
    return 0;
}
int after_main(void)
{
    
    
	printf("调用main()之后调用的函数\n");
	printf("%s\n",__FUNCTION__);
	return 0;
}
typedef int func();
#pragma data_seg(".CRT$XIU")
static func * before[] = {
    
     before_main };
#pragma data_seg(".CRT$XPU")
static func * after[] = {
    
     after_main };
#pragma data_seg()

程序在VS2013中运行结果如下:

调用main()之前调用的函数
before_main
调用main()函数
main

程序在VS2019中运行结果如下:

调用main()之前调用的函数
before_main
调用main()函数
main

总结

在Linux环境中我们通过关键字attribute来指定程序的入口地址,证明了C语言不是必须从main函数开始执行,并且在main函数调用后,还可以调用我们指定的函数,但是在VS2013和VS2019中,得到的结果和Linux环境下得到的结果存在一些差别(具体什么原因我并没有深究)。

参考博文链接:https://blog.csdn.net/king_cpp_py/article/details/79435351
http://www.cnblogs.com/Anker/p/3462363.html

猜你喜欢

转载自blog.csdn.net/weixin_51363326/article/details/116210851