引言
突然想到以前没事干去看编译器编译之后的switch,static之类的产生的汇编代码,觉得有趣,switch写过了,这次写static。
static初始化
所有人都知道在函数内定义static变量后只会初始化一次,就像下面这样:
#include <iostream>
using namespace std;
int test(){
static int a = 10;
if (a==10){
cout << "a==10" << endl;
}
a = 5;
return a;
}
int main()
{
cout << test() << endl;
cout << test() << endl;
return 0;
}
输出
a==10
5
5
那么它是怎么实现的呢,编译器将它编译之后是怎样的呢?
猜测
最早我有个想法可能是这样:
//static int a = 10;
//int a 被放在了静态区
//所以 static int a = 10;被编译成类似下面这样的代码。
if (!(a & 0xA)) a = 10;
然后想了想,应该不可能,如果a在下面被改成其他值,那么进入函数后应该会又被改为10。
结论
最后还是直接看的汇编代码,从汇编看,一个static变量等于在静态区声明了2个变量,一个用来判断是否初始化过,一个就是变量本身。test函数的伪代码类似下面这样:
//dword_74BFCC 用来判断是否初始化过,是一个在静态区的地址
//dword_74BFD0 刚好就在dword_74BFCC旁边,这是我们static int a的a变量本身。
int test(){
if (!(dword_74BFCC & 1)){
dword_74BFCC |= 1u;
dword_74BFD0 = 10;
}
if (dword_74BFD0 == 10){
cout << "a==10" << endl;
}
dword_74BFD0 = 5;
return dword_74BFD0;
}
需要注意的是:编译器版本不同可能最终编译的代码也不同,我逆向一个古老程序时,static初始化代码并没有上锁。不过目前编译器都是上锁了的,请放心。