2021年5月29日 星期六

scanf 為什麼要一定要加&

scanf 為什麼要一定要加&

tags: 部落格文章

相信大家從一開始剛學程式的時候一定都踩過這個坑,沒有加&導致程式錯誤,找半天還找不到那種的。

為什麼要加最主要的原因是,透過地址的傳遞才能夠修改變數。



& 是什麼意思

簡單說就是獲取位址的意思。

所謂的變數,其實可以理解成位址的別名,就比如說你在地圖上搜尋臺北車站 和搜尋 台灣台北市中正區北平西路3號100臺灣 可以找到同一棟建築物是一樣意思。

下面的代碼演示一下結果

int TaipeiStation;
cout << "台北車站的地址是:" << &TaipeiStation << endl;

利用地址修改變數

而其中位址這個型態,可以在宣告的時候加個 * 號來儲存。

int  num;

//宣告的時候星號表示這個變數是一個指標
int* p = &num;

現在你可以透過別名 num 來修改記憶體中的數值

num = 10;

也可以透過地址來修改

// 使用的時候星號表示讀取地址中的數值
*p = 10;

透過函式修改變數

現在有了位址之後就可以把地址傳進函式了

void increase(int* num){
    num++;
}

使用的話就像這個樣子

int num;
increase(&num);

現在謎底就揭曉拉,就是因為這個原因才導致一定要加上取址符號的



如果不打取址符號會發生什麼

其實 scanf 只要是傳遞位址進去就可以,並不是說一定必須,只是加上才是正確的寫法。如果不是傳遞位址的話,程式也會自動把數據轉換成位址。

傳遞整數

試著直接把一個整數傳入scanf

int i;
scanf("%d", i);

上面的情況會把i傳進去,對於scanf來說就是會試圖去讀取i這個位址有什麼東西,但是i沒有給初始值,沒有給初始值得話預設會是一個垃圾值,垃圾值可以當作一個亂數,產生的原因是上一個程式用完沒清掉的結果

嘗試對於亂數的位址存取是非法的,所以會報錯

Visual Studio 對於未初始的變數是不給使用的,這段在上面會直接報錯


傳遞整數位置

剛剛的錯誤在於位址是非法的位址,現在我們嘗試傳遞一個合法的地址進去就可以執行了

int p;
int i=(int)(&p);
cout << "[HEX:" << &p << "], [DEC:" << (int)&p << "]" << endl;

scanf("%d", i);

printf("%d\n", p);
printf("%d\n", *((int*)i));

i是一個 int,會被隱式轉換成 int* 接著scanf就會對轉換出來的位址存取,如果是合法的位址那就不會有錯誤。

沒有留言:

張貼留言