C語言指標疑難雜症

2021-06-28 19:09:04 字數 2672 閱讀 8251

c語言指標疑難雜症

——許多時候,使用c語言編寫的**是難於閱讀的,但很多人卻熱衷於此。

從軟體工和的角度出發,**應該盡可能地易於閱讀,無論是多年後的你還是接手專案的別人。但c語言本身的就要比其他語言要難於理解許多,且很多人為了一時的方便,寫出了一些只有自己才能理解的**。本文不是**所有的比較難於理解的**,我們的主題是——指標。

1. c語言指標有一些習慣的用法,它不是疑難雜症,我們應該盡可能去理解它們並且使用它們,如下面的**:

#includeint main()

; int *p;

for (p = arr; p < arr + 7;)

return 0;

}

上面**的輸出將會是arr陣列內容本身,這裡的注意點就是*p++這個語句。這裡我不想向大家介紹c語言的運算子的優先順序和運算子的結合順序這些內容,因為我也不想記住這些東西。但要理解上面的這個表示式,上面的兩個內容又是必須的。但有例外,你只要理解下面對*p++的解釋就行了:

在上面這段**裡,*p++等價於*(p++),因此整個表示式的結果將會是資料內容本身而不是指標。又因為是後運算,所以p++立刻返回的結果的值還是之前p的值,p返回後,p的值才發生改變。**下面**的輸出:

#includeint main()

; int *p=arr;

printf("%p,%p,%p\n", p, p++,arr);

}

輸出為:

0038fb70,

0038fb6c,

0038fb6c

為了理解這個輸出,首先是要知道printf_s(vc編譯器的安全printf函式版本)的運算順序——右結合的。即從右到左進行運算,然後再對應位置輸出:它首先計算arr,然後返回;再計算p++,然後返回;最後計算p,然後返回。p++雖然執行了自加運算,但它的返回值還是它之前的值。因此arr和p++的結果相等,面第乙個輸出的p是p+1的結果。

這樣,上面的*p++就不難理解了,它等價於*(p++),它先自增p,然後返回自增p之前p的值作為結果,然後利用間接定址運算子取得p++返回值指向的值。又或者將它理解為:它先取得p指向的值,然後再將p進行自增運算。假如p=0038fb6c,那麼p++的返回值為0038fb6c,但再次用到p時,p的值是0038fb70(0038fb6c +4)

而同樣常見的還有(*p)++,它和++*p是等價的。它是先取得指標指向的值,然後再將這個值加1(如上面當p第一次指向arr時,(*p)++就是取得p指向的值22,然後再加上1(等於23))。這時的自加運算就是一般意義上的加1了,而不是指標運算的加1(實際上是指標的值加上相應的位元組數)。三個表示式(*p)++、*p++、++*p的返回值都是指標指向的變數型別,而不是指標型別。

2.請看下面的**:

#includeint main()

for (int i = 0; i < 5; i++)

return 0;

}

再看輸出:

如果你看不明白*(arr+i)表達的意思,那麼你就先看一下我的另一篇文章:《c語言指標四——指標與函式》,如果你不想看,我可可告訴你:在這裡*(arr+i)和arr[i]是等價的。但很多人仍會感到迷惑,因為上面竟然有乙個這樣的語句*(arr + i) = i + 5;這裡的迷惑來自於,在大家的潛意識裡,*(arr+i)返回的是乙個值,但怎麼可以對乙個值進行再賦值呢?其實這種擔憂是不必的,上面已經說過*(arr+i)和arr[i]是等價的,既然通過arr[i]可以修改陣列元素的值,那麼*(arr+i)也可以改變陣列相應元素的值。事實上,*(arr+i)返回的是對陣列第i位元素的引用,所以用這種方式來修改陣列元素是完全合法的,不要擔心。

3.c語言陣列支援負下標?

請看下面的**:

#includeint main()

; int *p = &arr[5];

printf_s("%d,%d",arr[5],p[-3]);

return 0;

}

輸出為:

5 2;

有人認為,上面使用了p[-3]來訪問了陣列的元素,那麼就說明c語言的陣列支援負下標。但我認為這種說法是相當錯誤的,因為p根本就不是乙個陣列,它只是乙個指向整型的指標——整型指標。表示式p[-3]實際上會被轉換成*(p+(-3))來進行運算。而arr才是乙個真正意義上的陣列,如果對arr進行了負下標的運算,如:arr[-3],這必定會發生錯誤。下面讓我們從記憶體的角度看一下c語言陣列不支援負下標的真正原因。必須再次說明,p不是乙個陣列,它只是乙個整型指標。

對於arr[-2]指向的記憶體空間,首先這個記憶體空間不一定是有效的,再次,即使這是乙個有效的記憶體空間,你也不一定有權訪問它,這就是為什麼陣列不支援負下標的原因——很多時候,它還會出錯。而p可以使用負下標的原因是因為經過運算後,得到的結果仍然指向乙個合法的記憶體區域,在這個例子中,如果進行p[-7]求值,它必定也會出錯。

因此說,c語言陣列支援負下標是一種不負責任的說法,它混淆了陣列名和指標的區別,也沒有理解到本質的東西。

請記住,指標不是陣列,陣列名也不是指標,只不過很多時候,它們的使用可以等價的,但畢竟它們不是同一樣事物。

C 指標疑難雜症

const修飾指標 防止誤操作 const修飾指標,指標指向可以變,但是值不可以改變 int a 100,b 200 const int p a 指向可以變 p 100 值是不可以變const修飾變數,指標指向不可以改,指標的值可以改 int const p a 既修飾指標,又修飾常量 int a ...

Hadoop疑難雜症

前天安裝了pig,本來寫了條pig latin,但一直卡在 17 05 07 17 47 07 info mapreduce.job running job job 1494150363568 0001跑不通,想著肯定是mapredcue自身有問題,於是開始了艱苦的檢錯之旅,從csdn到stackf...

Appium疑難雜症

坑之初體驗 1.session大於60秒沒接收到命令自動關閉 python desired caps 在啟動配置裡面加入newcommandtimeout引數 desired caps newcommandtimeout 200 但是注意cnpm預設在當前目錄安裝npm包。3.uiautomatio...