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
? /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語言可否自定義數值類型(或是任意個位元組的數值類型)?
※利用異或方式交換兩個變數值的原理是什麼?
※為什麼計算機里加上存儲功能可以代替改變電路?