1. 程式人生 > >征服C指標(講那麼複雜,中國人永遠都別想超越美國人)

征服C指標(講那麼複雜,中國人永遠都別想超越美國人)

征服C指標(講那麼複雜,中國人永遠都別想超越美國人)

一段永久掉坑的程式碼

#include <stdio.h>

void one_set(int num)
{
    num = 11;
}

void two_set(int *num) //掉坑一,蒙圈
{
    *num = 11; //掉坑二,淚奔
}

int main(void)
{
    int one =
1; int two = 2; one_set(one); two_set(&two); //掉坑三,又掉坑,沒得救啦 printf("one = %d; two = %d\n", one, two); return 1; }

儲存為demo.c 執行gcc -g demo.c -o demo然後執行./demo 輸出結果是

one = 1; two = 11

結果沒有錯誤,為什麼掉坑

掉坑一:形參到底表示什麼意思?two_set函式樣子跟one_set一樣,能看出區別嗎?

大神說:不是有星號嗎?看得出來是傳入記憶體地址,不想跟傻逼聊天了!
我回復:那為啥你寫的程式碼,不寫成 void two_set(int* num) 更好

掉坑二:這賦值語句是啥?num就是普通數字,前面加個星號,是搞笑的嗎?

大神說:指標的意思呀,num的指標指向11,用屁股想想都明白!
我回復:那為啥你寫的程式碼,不寫成 *addr = 11; 更好

掉坑三:我去,我就喜歡實參傳入two,你就偏偏寫成&two,氣死人!

大神說:&這個符號,不懂就去學唄
我回復:我就偏偏不學,我要換另一種寫法

與大神對話後,我換了另一種寫法

#include <stdio.h>

void one_set(int num)
{
    num = 11;
}

void two_set
(int* addr) //掉坑一,蒙圈 { *addr = 11; //掉坑二,淚奔 } int main(void) { int one = 1; int two = 2; int* twoAddr = &two; int threeAddr[] = {1,2,3}; one_set(one); two_set(twoAddr); //掉坑三,又掉坑,沒得救啦 two_set(threeAddr); printf("one = %d; two = %d\n", one, two); printf("three[0] = %d; three[1] = %d\n", threeAddr[0], threeAddr[1]); return 1; }

儲存為demo.c 執行gcc -g demo.c -o demo然後執行./demo 輸出結果是

one = 1; two = 11
three[0] = 11; three[1] = 2

解釋為什麼這樣子寫

  1. 變數加上Addr表示是地址的意思,two_set函式內容表達的意思特別清晰,即傳入地址指向數字11。
  2. 書本表示陣列,喜歡用arr[] = {1,2,3}。通過該程式碼threeAddr對比,發現書本上arr其實是地址的意思。
  3. 另外驚訝發現,two_set函式居然可以用於int和int陣列,測試結果可以改變threeAddr陣列第一個元素為11。
  4. 得出來結論:threeAddr陣列是有連續3個地址,第一個地址是threeAddr,指向數字1。從而明白了記憶體結構。
*threeAddr threeAddr [0] 1
*(threeAddr+1) threeAddr [1] 2
*(threeAddr+2) threeAddr [2] 3