1. 程式人生 > >C語言再學習 -- 再論陣列和指標

C語言再學習 -- 再論陣列和指標

之前有總結指標陣列,但是現在看來總結的太簡單了。好多重要的知識點都是一帶而過的。本想在後面新增後來想想算了,還是再寫一篇文章來詳細介紹陣列和指標這對冤家吧。

一開始覺得C語言再學習專欄都寫了五十篇了,現在的C語言水平至少可以說熟練掌握吧。有點洋洋得意的感覺,但是總結這章的時候,我有點急躁了。忽然覺得自己還是什麼都不明白,之前的對C語言的認知只是冰山一角。迫切想著趕緊把這章總結完,部分內容複製貼上過度了,好多內容都沒有吃透。自責! 這不應該是我現在的狀態。靜下心來、從新梳理,再論陣列和指標!!

一、指標

1、首先要搞清楚什麼是指標?

int n = 5;  
int *ptr = &n;     
*ptr = 5;   

ptr的值是n的地址,*ptr是儲存在地址&n中的數值

所以,可以看出指標是一個其數值為地址變數

2、指標記憶體佈局

int *p;  
char *c;  
double * d;  

上述都為指標,在 32 位系統下,不管什麼樣的指標型別,其大小都為 4byte。與“ *”號前面的資料型別無關,

“ *”號前面的資料型別只是說明指標所指向的記憶體裡儲存的資料型別。

3、應避免未初始化和非法的指標

下面這個程式碼說明了一個極為常見的錯誤:

  1. #include <stdio.h>
  2. void main()    
  3. {    
  4.     int *a;  
  5.     *a = 10;  
  6. }  
  7. 輸出結果:  
  8. 段錯誤 (核心已轉儲)  
因為。指標未進行初始化,對於一個NULL指標進行解引用操作是非法的。

4、指標表示式

現在讓我們觀察各種不同的指標表示式,並看看當它們分別作為左值和右值時是如何進行求值的。

我們以下面例子為例展開討論:

  1. char ch = 'a';  
  2. char *cp = &ch;  
1)表示式:ch

它作為右值使用時,表示式的值為 'a';  但當這個表示式作為左值使用時,它是這個記憶體的地址而不是該地址所包含的值。

  1. #include <stdio.h>
  2. void main()    
  3. {    
  4.     char ch = 'a';  
  5.     char *cp = &ch;  
  6.     char c = ch;  
  7.     printf ("%c, %c\n", ch, c);  
  8. }  
  9. 輸出結果:  
  10. a, a  

2)表達式:&ch

作為右值,這個表示式的值是變數 ch 的地址。作為左值是非法的。一方面,優先順序表格顯示&操作符的結果是個右值,它不能作為左值使用。另一方面,當表示式&ch進行求值時,你不知道它的結果應該儲存在計算機的什麼地方,這個表示式並未標識任何機器記憶體的特定位置,所以它不是一個合法的左值。

  1. #include <stdio.h>
  2. void main()    
  3. {    
  4.     char ch = 'a';  
  5.     char *cp = &ch;  
  6.     //&ch = cp;錯誤: 賦值運算的左運算元必須是左值
  7.     printf ("%p\n", &ch);  
  8. }  
  9. 輸出結果:  
  10. 0xbf8bf8cf  

3)表示式:cp

作為右值為 cp的值,它作為左值就是cp所處的記憶體位置。

  1. #include <stdio.h>
  2. void main()    
  3. {    
  4.     char ch = 'a';  
  5.     char *cp;  
  6.     cp = &ch;  
  7.     char *p = cp;  
  8.     printf ("%p\n", cp);  
  9. }  
  10. 輸出結果:  
  11. 0xbfb9f6bf  

4)表達式:&cp

作為右值為指標變數的地址,也就是字元的指標的指標。它作為左值是非法的

  1. #include <stdio.h>
  2. void main()    
  3. {    
  4.     char ch = 'a';  
  5.     char *cp = &ch;  
  6.     char **p = &cp;  
  7.     //&cp = p;  錯誤: 賦值運算的左運算元必須是左值
  8.     printf ("%p\n", p);  
  9.     printf ("%p\n", *p);  
  10.     printf ("%p\n", cp);  
  11. }  
  12. 輸出結果:  
  13. 0xbffe1c94  
  14. 0xbffe1c9f  
  15. 0xbffe1c9f  

5)表示式:*cp

它等同於ch,它作為右值表示式的值為'a',但當這個表示式作為左值使用時,它是這個記憶體的地址而不是該地址所包含的值。

  1. #include <stdio.h>
  2. void main()    
  3. {    
  4.     char ch = 'a';  
  5.     char *cp = &ch;  
  6.     char c = *cp;  
  7.     *cp = 'b';  
  8.     printf ("%c\n", *cp);  
  9.     printf ("%c\n", c);  
  10. }  
  11. 輸出結果:  
  12. b  
  13. a  

6)表示式:*cp + 1

這裡有兩個操作符, * 的優先順序高於 +,所以首先執行間接訪問操作。我們取得這個值的一份拷貝並把它與 1 相加,表示式的最終結果為字元 'b'。這個表示式的最終結果的儲存位置並未清晰定義,所以它不是一個合法的左值。優先順序表格證實 + 的結果不能作為左值。

  1. #include <stdio.h>
  2. void main()    
  3. {    
  4.     char ch = 'a';  
  5.     char *cp = &ch;  
  6.     char c = *cp + 1;  
  7.     //*cp + 1 = 'c';   錯誤: 賦值運算的左運算元必須是左值
  8.     printf ("%c\n", *cp);  
  9.     printf ("%c\n", c);  
  10. }  
  11. 輸出結果:  
  12. a  
  13. b  

7)表示式:*(cp + 1)

這個括號表示式先執行加法運算,就是把 1 和 cp 中所儲存的地址相加。這樣,這個表示式作為右值就是這個位置的值,而它的左值是這個位置本身。

但是,這個表示式所訪問的是ch後面的那個記憶體位置,一般而言,我們無法得知,所以像這樣的表示式是非法的。

  1. #include <stdio.h>
  2. void main()    
  3. {    
  4.     char ch = 'a';  
  5.     char *cp = &ch;  
  6.     *(cp + 1) = 'd';    
  7.     char c = *(cp + 1);  
  8.     printf ("%c\n", *cp);  
  9.     printf ("%c\n", c);  
  10.     printf ("%c\n", *(cp + 1));  
  11. }  
  12. 輸出結果:  
  13. a  
  14. d  
  15. d  
8)表示式:++cp

相關推薦

C++反彙編學習筆記7——陣列指標以及他們的定址

兩年前寫的,歡迎大家吐槽!  轉載請註明出處。 1.      陣列在函式內 先通過一個簡單的例子來看一下陣列和普通變數在初始化時的不同之處: 這是陣列初始化:     42:   int nArry[5] = {1, 2, 3, 4, 5}; 0042B758  mov 

C語言學習 -- 陣列指標

之前有總結指標陣列,但是現在看來總結的太簡單了。好多重要的知識點都是一帶而過的。本想在後面新增後來想想算了,還是再寫一篇文章來詳細介紹陣列和指標這對冤家吧。一開始覺得C語言再學習專欄都寫了五十篇了,現在

C語言-自我學習-遍歷陣列

人懶要多記筆記 sizeof這個關鍵詞能獲取到這個陣列在記憶體所佔用的位元組數 int是佔4個位元組 那麼如果我獲取到這個位元組數,然後去除去陣列的第一個索引的位元組數,就得到了陣列長度 得到動態長度就可以開始遍歷了 在c中,是沒有自動換行的方法,所以需要加上\n i

C語言之指向一維陣列指標

int array[5] = {1, 2, 3, 4, 5}; // 定義陣列 int *intptr = array; // 定義指向陣列元素的指標 int (*arrayptr)[5] = &array; // 定義指向陣列的指標 上述三條語句分別

c++ primer》第四章--陣列指標

陣列是c++中類似於標準庫vector型別的內建資料結構,與vector相似,陣列也是一種儲存單一型別物件的容器,其中每個物件沒有單獨的名字,而是通過它在陣列中的位置對它進行訪問。 與vector型別相比,陣列的顯著缺陷在於:陣列的長度是固定的,而且程式設計師無法知道一個指

C Primer Plus 第十章——陣列指標

 與普通變數相似,在初始化之前陣列元素的數值是不定的。編譯器使用的數值是儲存單元中已有的數值。初始化陣列元素時(int),當數值數目少於陣列元素數目時(部分初始化),多餘的陣列元素被初始化為0。如果初始化列表中專案的個數大於陣列大小,編譯器則會認為這是一個錯誤。可以在初始化

C語言學習 -- 記憶體管理

但現在看來,缺少示例。從新再寫一篇文章,著重介紹常見記憶體錯誤、跨函式使用儲存區。開始吧,再論記憶體管理!!發生記憶體錯誤是件非常麻煩的事情。編譯器不能自動發現這些錯誤,通常是在程式執行時才能捕捉到。而這些錯誤大多沒有明顯的症狀時隱時現增加了改錯的難度。一、常見的記憶體錯誤及

C語言學習筆記---C專家程式設計 什麼時候陣列指標相同

 什麼時候陣列和指標是相同的: 規則1:表示式中的陣列名(與申明不同)被編譯器當作指向該陣列第一個元素的指標 規則2:下標總是與指標的偏移量相同 規則3:在函式引數的宣告中,陣列名被編譯器當作指向該陣列第一個元素的指標 規則1的例外情況: 1、陣列作為sizeo

C語言學習(3):陣列指標

前言 上一篇部落格講了指標的用法,本章來講陣列。首先明確一點,陣列也是指標。 正文 1、陣列的幾種定義 int arr[5]; //不初始化 int arr[5] = {1,2,3,4,5}; //初始化 int arr[] = {1,2,3,

C語言學習(六)──學習C語言的認知、態度

    談到這點上,很多老師會覺得多看、多練就可以提高C語言水平的,我相信你現在也是這麼認為的。的確不假,這是非常重要的一步。但是前提是你願不願意去多看、多練上。如果學習C語言只會讓你更加痛苦,或者C語言與你理想相差太遠

C語言學習(七)──學習C語言的方法

    如果你打定了要學好C語言,那麼請看下面的方法吧,雖然我學習C語言的時候沒有用上,但是現在學習新知識新技術的時候很管用──不管學的是什麼。因此大家可以試試,或許還有比這些方法更有效的方法,不妨也寫出來交流交流。實際上我這裡是想教大家怎麼面對一個新事物,並用有效的辦法學習

c語言 將一個二維陣列列的元素互換,存到另一個二維陣列

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

C語言入門學習書籍推薦

1、C語言適合當第一門程式語言學習 ①、C語言語法相對簡單,但又比較完整和嚴謹,包含該有的各種元素。學完C語言語法,要學習其它程式語言就很容易了。 ②、C語言接近底層,可以瞭解記憶體和計算機的基本原理。 ③、許多基礎課程比如演算法與資料結構教材都是以C

FFmpeg學習 -- SDL 環境搭建視訊顯示

/** * 最簡單的基於FFmpeg的視訊播放器2(SDL升級版) * Simplest FFmpeg Player 2(SDL Update) * * 雷霄驊 Lei Xiaohua * [email protected] * 中國傳媒大學/數字電視技術 * Communication Unive

C語言程式設計 學習筆記 字串(II)(字串輸入輸出,字串陣列,程式引數)

字串輸入輸出: char str[8]; scanf("%s",&str); printf("%s",str); scanf表示讀入一個單詞(到空格、tab、回車為止) scanf是不安全的,因為這樣不知道要讀入的內容的長度,在一些情況中會出現問題:

C語言_結構體巢狀字串陣列的表示_plusC14.3

#include<stdio.h> #define LEN 20 const char *mgs[5]= {"qqqq","wwww","EEEEEEE","RRRR","TTTTT" }; struct apple {char smell[LEN];char

c語言基礎(3) 陣列指標作為實參形參的問題

字串 char a[]="abc"; printf("%s",a); fgets(a,100, stdin) //安全的字串輸入函式 printf("%s",a); scanf("%*[^\n]"); //兩個scanf清空輸

c++語言 如何計算二維陣列行數列數

對於一個二維陣列如: int a[2][5]; 求陣列元素的總數: sizeof(a) / sizeof(int) 而陣列行數則為 :( sizeof(a) / sizeof(int) )/ ( sizeof(a[0]) / sizeof(int) ) 求陣列列數: siz

傳智播客c/c++公開課學習筆記--C語言與木馬惡意程式碼分析360安全防護揭祕

【課程簡介】 C/C++語言是除了彙編之外,最接近底層的計算機語言,目前windows,linux,iOS,Android等主流作業系統都是用C/C++編寫的,所以很多病毒、木馬也都是用C/C++實現的。課程的目的就是通過C語言揭祕木馬和各種遠端控制軟體的實現原理以及如

Go語言學習筆記2——陣列Slice

     在任何一門語言裡,陣列應該都是非常基礎的型別了,使用率當然也應該是很高的。go不但提供了陣列,而且還在陣列這個型別之上加了一層包裝,這個包裝也就是slice。         go的陣列變數(也就是陣列名)是真真實實的陣列,而不是一個指向陣列記憶體起始位置的指標,