4

在 main 函数之前执行代码(C 语言)

 2 years ago
source link: https://blog.csdn.net/lyndon_li/article/details/120160343
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

main 函数

又称主函数,是程序执行的起点。

在 main 函数之前

那么,我们有办法在 main 函数之前执行代码吗?

答案是肯定的。

before_main.c

#include <stdio.h>

__attribute((constructor)) void before_main()
{
	printf("%s\n", __FUNCTION__);
}

int main(int argc, char **argv)
{
	printf("%s\n", __FUNCTION__);
	return 0;
}

编译 && 执行

$ gcc before_main.c -o before_main.out
$ ./before_main.out 
before_main
main

看到,先运行 before_main(),再运行 main()

GNU C 的一大特色就是 attribute 机制。attribute 可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。
__attribute__书写特征是:attribute 前后都有两个下划线,并且后面会紧跟一对括弧,括弧里面是相应的 attribute 参数。

constructor 属性可以使函数在 main 函数之前执行

再往底层想,C 语言中,main 函数是程序的入口点 这件事情本来就是 gcc 编译器 决定的。那么 gcc 当然可以指定任何函数作为程序的入口,这点在我之前写的一篇文章《没有了 main 函数,程序还能跑吗?》中也有介绍。

这里又是通过另一种方式来影响程序入口点的,即 __attribute((constructor)) 方式。

在 main 函数之后

不光有 constructor 属性能够实现在 main 函数之前执行代码;还有属性 destructor,能够实现在 main 函数之后执行代码。如下:

#include <stdio.h>

__attribute((constructor)) void before_main()
{
	printf("%s\n", __FUNCTION__);
}

__attribute((destructor)) void after_main()
{
	printf("%s\n", __FUNCTION__);
}

int main(int argc, char **argv)
{
	printf("%s\n", __FUNCTION__);
	return 0;
}
$ ./before_main.out 
before_main
main
after_main

C++ 类的构造函数、析构函数

多像 C++ 中类的构造函数和析构函数啊。

类的 构造函数 是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。

类的 析构函数 是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。
析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。

#include <iostream>

using namespace std;

class Line {
public:
	void setLength(double len);
	double getLength(void);
	Line();	  // 这是构造函数声明
	~Line();  // 这是析构函数声明

private:
	double length;
};

// 成员函数定义,构造函数
Line::Line(void)
{
	cout << "Object is being created" << endl;
}

Line::~Line(void)
{
	cout << "Object is being deleted" << endl;
}

void Line::setLength(double len)
{
	length = len;
}

double Line::getLength(void)
{
	return length;
}

int main()
{
	Line line;

	// 设置长度
	line.setLength(6.0);
	cout << "Length of line : " << line.getLength() << endl;

	return 0;
}
Object is being created
Length of line : 6
Object is being deleted

纵向思考 && 横向联想

学习的两个好方法:纵向思考和横向联想。
纵向思考能够让你认清事物本身,让你对事物的理解更加深刻、正确。

就像我们对 C 语言的程序入口的思考一样,C 语言是被 gcc 编译成可执行文件的,从这个角度思考,gcc 的权利是大于 C 语言的,它让你的哪个函数成为程序的入口点,就让哪个函数称为入口点。main 函数作为程序的入口点只是大家共同的约定,gcc 可以无视。

横向联想能够让你发现多个事物之间的共同点,能够让你举一反三,达到触类旁通的效果。

就像从 C 语言的 constructor 属性和 destructor 属性联想到 C++ 的构造函数和析构函数

这两个方法也是帮助我们成为 T 型人才的有力工具,我们要好好利用它。
在这里插入图片描述


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK