很久沒(méi)出來(lái)搞事情了慨绳,今天我們來(lái)在 main 函數(shù)之前搞搞事情爱榔。
寫(xiě)匯編的大神看到可能要笑了被环,我一直都在 main 函數(shù)前搞事情啊,要不是我搞好運(yùn)行時(shí)環(huán)境详幽,設(shè)置好棧蛤售,看你怎么運(yùn)行哦。
那寫(xiě) c 不同啦妒潭,想要在 main 前搞事情悴能,那得借助 gcc 的黑魔法 __attribute__。
話不多說(shuō)雳灾,直接上碼:
#include <stdio.h>
#include <stdint.h>
__attribute__((constructor)) void test01(void)
{
printf("gao shi qing before main...\r\n");
}
int main(int argc, char *argv[])
{
printf("hello world!!!\r\n");
return 0;
}
使用 gcc 編譯后運(yùn)行會(huì)得到如下結(jié)果:
gao shi qing before main...
hello world!!!
沒(méi)錯(cuò)漠酿,就是神奇的 __attribute__((constructor)) 使得 test01 函數(shù)能在 main 函數(shù)之前被調(diào)用。
神奇是神奇谎亩,那有什么用處呢炒嘲?
該黑魔法在使用的時(shí)候任何文件任何地方都能生效,對(duì)于一個(gè)有初始化函數(shù)的模塊來(lái)說(shuō)匈庭,可以對(duì)其使用該黑魔法夫凸,這樣就省去了自己顯性的在 main 函數(shù)過(guò)程中調(diào)用它的初始化函數(shù),讓 gcc 來(lái)幫我們自動(dòng)完成阱持,對(duì)于使用該模塊的人來(lái)說(shuō)也省心省力夭拌。
其他還有什么用處各位可以發(fā)揮自己的腦洞了。
有 constructor 那當(dāng)然就有 destructor。聰明的你肯定能想到被 __attribute__((destructor)) 加持的函數(shù)肯定是會(huì)自動(dòng)的在 main 函數(shù)執(zhí)行完畢后被自動(dòng)調(diào)用鸽扁。
有人可能會(huì)舉手了蒜绽,如果有很多有 __attribute__((constructor)) 加成的函數(shù)它們誰(shuí)先執(zhí)行呢?
gcc 也為我們想好了桶现,它提供了讓我們?cè)O(shè)置優(yōu)先級(jí)的功能躲雅,如下:
__attribute__((constructor(101))) void test01(void)
{
printf("test01 gao shi qing before main...\r\n");
}
__attribute__((constructor(102))) void test02(void)
{
printf("test02 gao shi qing before main...\r\n");
}
這樣寫(xiě)清楚后,test01 就會(huì)優(yōu)先于 test02 執(zhí)行骡和,使用 destructor 時(shí)同理相赁,有點(diǎn)不同的是 destructor 時(shí)數(shù)值越大的越先得到執(zhí)行,和 constructor 正好相反慰于。
為什么是從 101 開(kāi)始的呢噪生,因?yàn)槲姨?1 的時(shí)候被 gcc 警告了,1 到 100 它要留著用东囚。
說(shuō)完 c 那我們?cè)賮?lái)說(shuō)說(shuō) c++ 吧跺嗽。
c++ 當(dāng)然也可以使用 __attribute__ 的黑魔法啦,但人家還有對(duì)象页藻。
沒(méi)錯(cuò)桨嫁,就是對(duì)象,對(duì)象有構(gòu)造和析構(gòu)函數(shù)份帐,我們定義了一個(gè)全局的對(duì)象后璃吧,那它的構(gòu)造函數(shù)和析構(gòu)函數(shù)就會(huì)分別在 main 函數(shù)之前和之后被調(diào)用了(好像很厲害的樣子,誰(shuí)讓人家有對(duì)象)废境。
上碼試試:
#include <stdio.h>
#include <stdint.h>
__attribute__((constructor(101))) void test01(void)
{
printf("test01 gao shi qing before main...\r\n");
}
__attribute__((constructor(102))) void test02(void)
{
printf("test02 gao shi qing before main...\r\n");
}
class test{
public:
test()
{
printf("test object gao shi qing before main...\r\n");
}
~test()
{
printf("test object gao shi qing after main...\r\n");
}
};
test test_instance; // global object
int main(int argc, char *argv[])
{
printf("hello world!!!\r\n");
return 0;
}
__attribute__((destructor(102))) void test03(void)
{
printf("test03 gao shi qing after main...\r\n");
}
__attribute__((destructor(101))) void test04(void)
{
printf("test04 gao shi qing after main...\r\n");
}
最終它的輸出如下:
test01 gao shi qing before main...
test02 gao shi qing before main...
test object gao shi qing before main...
hello world!!!
test object gao shi qing after main...
test03 gao shi qing after main...
test04 gao shi qing after main...
好了畜挨,今天就搞到這里了,搞的不好的地方歡迎留言指正噩凹,下次見(jiàn)巴元。
掃碼關(guān)注我了解更多