什麼是變量
變量在C語言中就是一個容器,通常是一塊內存。
聲明變量
變量類型 變量名;
例如:
int x;
在上面的代碼裏,int就是變量類型,x就是變量名。變量類型用來說明數據寬度,變量名的命名規則與函數名一致。。
變量類型 | 數據寬度 |
---|---|
int | 4個字節 |
short | 2個字節 |
char | 1個字節 |
全局變量
- 編譯的時候就已經確定了內存和寬度,變量名就是內存地址的別名。
int x; //聲明變量
void main() //入口
{
x = 1; //賦值
return; //程序結束
}
我們從反彙編中查看一下這個程序,從這裏可以看到,全局變量它有一個獨一無二的內存編號,從這裏我們可以理解,什麼是變量名?變量名就是內存地址的別名。
-
如果不重寫編譯,全局變量的內存地址不變,遊戲外掛中找“基址”其實就是找全局變量。
這句話怎麼理解呢,就是我們編寫完程序按F7構建,現在我不按F7了,依然是剛纔的程序,我直接按F5讓它運行,我們看一下它內存地址的變化:
int x; //聲明變量
void main() //入口
{
x = 1; //賦值
return; //程序結束
}
可以看到,內存地址沒有發生變化,也就是隻要不重建,內存編號就始終不會改變。
做一個小“外掛”
我們做一個小實驗,假設我們在玩傳奇,下面的這一段代碼是我們的攻擊頻率與攻擊力,我們怎麼樣來達到每刀999的效果呢?
#include <stdio.h>
#include <windows.h> //文件頭
int x; //全局變量
void main() //程序入口
{
x = 80; //攻擊力
while(1) //攻速
{
Sleep(3000); //每3秒砍一刀
printf("%d\n",x); //輸出攻擊力
}
return; //程序結束
}
這裏用到一款軟件,CE,它可以修改程序的變量,我們先打開CE,把程序跑起來,可以看到,這裏每3秒砍一刀,一刀80,接下來我們就讓它每刀999
把文件加載到CE裏,具體怎麼加載這裏不多介紹。
搜一下80這個變量,這裏有一個綠色的,這就是全局變量,咱們更改變量數值爲999
點擊確定,看看效果如何。
這樣我們接下來砍的每一刀都是999,外掛的原理跟這個是一樣的,只不過操作起來麻煩一點罷了,這裏我們就用到了上文所說的“基址”,也就是確定了的全局變量的地址。
也就是說:
- 全局變量中的值任何程序都可以改,是公用的。
局部變量
- 局部變量是函數內部申請的,如函數沒有執行那麼局部變量沒有內存空間。
- 局部變量的內存是在堆棧中分配的,程序執行時才分配,我們無法預知程序何時執行,這也就意味着,我們無法確定局部變量的內存地址。
- 因爲局部變量內存地址是不確定的,所以局部變量只能在函數內部使用,其他函數不能使用。
之前的變量我們是在函數外面聲明的,現在我們把它刪掉,在函數內部聲明。
#include <stdio.h>
#include <windows.h>
int plus() //定義函數
{
int x; //局部變量
x = 123456; //賦值
return 0;
}
void main() //這裏加這個函數是爲了不讓程序掛掉
{
;while(1) //無限循環
{
Sleep(3000);
}
return;
}
這段代碼執行以後,我們是搜不到“123456”這個局部變量的,原因很簡單,就是局部變量沒有使用,它沒申請內存地址,所以我們用CE搜多少次都是搜不到的。
我們修改一下代碼,讓函數調用這個局部變量:
#include <stdio.h>
#include <windows.h>
int plus() //定義函數
{
int x; //局部變量
x = 123456; //賦值
while(1) //延長程序的執行時間
{
Sleep(3000);
}
return 0;
}
void main()
{
plus();
return;
}
這裏用CE雖然搜到了,但是它並不是全局變量,而且每次搜到的地址都是不一樣的,這也證實了上面的觀點。
所以局部變量與全局變量最大的差異就是:局部變量在函數邊,函數用它纔有值,函數不用,它就沒有值,而且它的地址沒法確定,因爲我們也不知道這個函數什麼時候會被調用。
關於變量的初始值
這裏全局變量可以沒有初始值,系統默認爲零,是可以直接使用的。
例如這段代碼:
#include <stdio.h>
#include <windows.h>
int x; //定義全局變量
void main() //程序入口
{
while(1) //無限循環,每一秒輸出一個x的值
{
Sleep(1000);
printf("%d\n",x);
}
return; //程序結束
}
運行結果可以看到,我們並沒有給x賦值,系統默認NULL就給它賦值爲0.
但是局部變量爲什麼不可以呢?下面這段代碼執行報錯:
#include <stdio.h>
#include <windows.h>
int plus()
{
int x;
{
// x = 666;
while(1)
{
Sleep(1000);
printf("%d\n",x);
}
}
}
void main()
{
plus();
return;
}
這是因爲,未初始化的局部變量的值是不確定的,上一次誰使用過這一塊的棧區,恰好留在局部變量所在區域的值等於幾,這次局部變量的未初始化的默認值就是幾,這一點是非常麻煩的,所以一定要給局部變量初始化。
總結
- 變量就是一個容器。
- 變量類型用來確定變量的內存寬度。
- 變量名就是內存的編號。
- 全局變量中的值任何程序都可以改,是公用的。
- 局部變量必須初始化。