C/C++中如何在main()函數之前執行一條語句?

別人參加網易面試被問到這個題,然後我查了一下,大概有幾種方法:

在C語言中,如果使用GCC的話,可以通過attribute關鍵字聲明constructor和destructor(C語言中如何在main函數開始前執行函數)

#include &

__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;
}

在C++中,利用全局變數和構造函數的特性,通過全局變數的構造函數執行(C++語言怎麼在main函數執行之前執行一段代碼)

#include &
using namespace std;

class TestClass
{
public:
TestClass();
};

TestClass::TestClass()
{
cout&<&<"TestClass"&<&

現在想請教一下,是否還有別的方式可以在main()函數之前執行代碼?多謝


其實很簡單。。

程序嘛,講求物理和邏輯也就是直接和間接

物理(直接)的方法,可以用linker指定入口,如下:

? /tmp cat xiao.c
#include&

int
main(int argc, char **argv) {
printf("main
");

return 0;
}

int
xiao(int argc, char **argv) {
printf("xiao
");

return main(argc, argv);
}
? /tmp cc xiao.c -e _xiao ./a.out echo $?
xiao
main
0
? /tmp

邏輯(間接)的方法,可以用main調用main實現在main前執行一段代碼,如下:

? /tmp cat jing.c
#include&
#include&

int
main(int argc, char **argv) {
static _Bool firstTime = true;
if(firstTime) {
firstTime = false;
printf("BEFORE MAIN
");
return main(argc, argv);
}

printf("main
");

return 0;
}
? /tmp cc jing.c ./a.out echo $?
BEFORE MAIN
main
0
? /tmp

兩種方法相比較,當然是第二種更好,雖然是間接,但是代碼一眼就看懂了,第一種方法要用注釋文檔寫清楚,所以不那麼好。

其他方法,都是利用副作用實現這個功能,所以就顯得更加不好了。

請記住這個原則:【程序最重要的是直觀,副作用要少】

最近風傳的windows 10的笑話,就是因為寫程序利用副作用帶來的惡果

os.startWith("Windows 9")
// 程序邏輯最好不要利用副作用,應該寫成下面這樣
os == "Windows 95" || os == "Windows 98"
// 如果項目很多,比如90-99都有甚至900-999都有,那麼應該用查表的方法
validOSNames = ["91", "92", ... "99"];
validOSNames.contains(os)


// C++11
#include &

int a = []() {
std::cout &<&< "a"; return 0; }(); int main() { std::cout &<&< "b"; return 0; }


記得在鏈接時可以指定入口函數與入口前、入口後的函數。


1、全局變數的構造函數

2、全局變數的賦值函數

3、指定入口點,入口點中調用原來的入口點


#include &

using namespace std;

int foo(void);

int i=foo();

int foo(void)

{

cout&<&<"before main"&<&

return 0;

}

int main(void)

{

cout&<&<"i"m main"&<&

}


全局類變數的構造都在main之前


在Windows上,main不是第一個執行的函數代碼,exe的entry point function才是,默認名字就是WinMain。

實際上是 msvcrt 實現了 entry point,在裡面初始化 CRT,然後再調用代碼里的 main函數的。


用宏構造出這樣的結構就可以了,我自己的單元測試就是這麼乾的,簡單粗暴:

class Fuck
{
public:
Fuck()
{
// 代碼放這裡
}
} fuck;


歪個樓,之前在看雪上看到過:TLS(線程本地存儲器)。

比如為了防止軟體被破解,會對OEP進行一個檢測,如果為CC則退出程序,那麼檢測程序就要寫在TLS里,這個是先於程序任何代碼執行的。

具體的可以參見《加密與解密》第三版297頁。

這裡丟一個連接:關於TLS編程


int f(){
// do something
return 0;
}
int _ = f();
int main(){
return 0;
}


--wrap=main


退出的時候有onexit,開始之膽就是全局變數?


構造函數。。。


把這句話寫到上幾個被執行的程序中去。就可以了。


全局靜態類,就是聲明一下,調用構造,在構造里折騰。

可以參考註冊消息或註冊服務的宏定義。


剛學。。全局類構造在main或winmain之前


推薦閱讀:

哪些類型的應用必須用c語言寫?
關於菲波那契數列的一個低級問題?
C語言可否自定義數值類型(或是任意個位元組的數值類型)?
利用異或方式交換兩個變數值的原理是什麼?
為什麼計算機里加上存儲功能可以代替改變電路?

TAG:編程語言 | 編程 | C編程語言 | C |