程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 對指針的學習總結,指針學習總結

對指針的學習總結,指針學習總結

編輯:關於C語言

對指針的學習總結,指針學習總結


  1 /*----------------------------------------
  2           指針練習(精華)
  3 
  4     1)首先,要理解變量或數組的首地址,指的就是存放數據的RAM或ROM中地址號最小的那個字節地址。
  5     2)指針前面的類型說明符,具有2重意義(既決定了對一級指針進行解引用時,將會操作的字節數,以及對一級指針進行算術運算時,會跳轉的地址個數)。    
  6       ①決定了指針加一時,指針會跳轉多少個地址,
  7       例如:
  8               如果指針是
  9               char類型的,(指針+n) 指針會跳轉n*1個地址。
 10               int 類型的,(指針+n) 指針會跳轉n*2個地址。
 11               long類型的,(指針+n) 指針會跳轉n*4個地址。
 12               
 13       ②並且還決定了通過指針操作地址值時,實際上會返回多少個字節的值,且地址號大的字節先返回。 
 14       例如:    
 15               假設要操作指針的一次地址返回值,那麼如果指針是
 16               char類型的,返回1個字節。
 17               int 類型的,返回2個字節。
 18               long類型的, 返回4個字節。
 19               
 20       數組前面的類型說明符,同樣具有2重意義,且跟上面的很相似。
 21       例如:
 22               #include"stdio.h"
 23               int c[]={0x1234,0x5678};
 24               void main()
 25               {
 26                 printf("%p %d\n",c,*c);            //數組是int類型意味著返回2個字節
 27                 printf("%p %d\n",(c+1),*(c+1));  //實際上(c+1)與c是夾著一個地址,因為數組類型符號是int,如果數組類型是long,則夾著3地址
 28               }
 29       
 30       也就是要注意類型所占的字節數,還有就是什麼時候該看數組類型符號或者指針類型符號。
 31     3)&叫取首地址符號,*叫解引用符號。
 32     4)數組名是指一個首地址,所以,point=a(point是一個指針,a是一個數組名), a的前面不需要加&符號。
 33       變量名指的是一個值,a[1]指的也是一個值,這些值包含著一個或多個字節,在想要讓指針指向這些值的字節的地址時,
 34       需要在變量名以及a的前面加上&符號,即意思是要讓指針賦值符號(=)右邊的東西是地址。
 35     5)數組或變量的數據是一個一個字節的存放的,而且字節的地址是呈現連續的,賦值的時候,從左到右看,
 36       越往右,字節的地址號越大。因此,對於多字節數據類型的數組而言,看起來有種“首尾相連”的效果,
 37       因為一個元素的最低位字節其地址的加一地址對應的字節,就是下一個元素的最高位字節。
 38       
 39       簡單點來說就是低地址存放高字節,這種現象稱為大端排列(常用單片機)。注意:有些時候則是低地址存放低字節,這種現象稱為小端排列(ARM)。
 40       
 41     6)指針可分為:函數指針,數組指針(多維指針),變量指針,結構體指針。  又可分為:多級指針,多維指針。  地址可分為:多級地址,多維地址。
 42     7)只有字符數組的最後一個元素會緊接一個隱藏元素,該元素值為0,映射的字符為“\0”。
 43     8)數據指針型函數,也叫指針函數(即返回值是一個地址)。       
 44     9)char (*p)[2];   //聲明一個二維指針(也叫二維數組指針)
 45       分析方括號([])對多維指針的操作時,要遵循一個原則:先明確指針的維數,再分析有多少組方括號,方括號裡面的數字是多少,由此得到地址是如何跳轉的;
 46                                                         然後根據方括號的組數得知地址最終會發生多少次的解引用,如果解引用的次數少於地址的維數,
 47                                                         那麼最終得到的還是一個地址,也如果解引用的次數等於地址的維數,那麼得到是一個數據值。
 48                                                         每次對多維地址進行一次解引用後,地址的維數將會變小。
 49       一維數組名就是一個一級一維地址,二維數組名就是一個一級二維地址,多維數組名就是一個一級多維地址。每一個數組名都是一個地址。這些地址是固定的。
 50       一級多維指針的特點是:解引用的寫法很特殊;運算時地址的跳轉很特殊。
 51       探究代碼如下:
 52       int Array[2][3][2]={{{1,2},{3,4},{5,6}},{{7,8},{9,10},{11,12}}};  
 53 
 54       printf("%d\n", Array); 
 55       printf("%d\n", Array[1]);   //與上一行代碼相比,發生了 3*2*4=24個地址 的跳轉
 56       printf("%d\n", Array[1][1]);    //與上一行代碼相比,發生了 2*4=8個地址 的跳轉
 57 
 58       printf("%d\n",*(Array[1][1]));//對1維地址進行1次解引用,得到一個數據值,為9
 59 
 60       printf("%d\n",*(*(Array[1])));    //對2維地址進行2次解引用,得到一個數據值,為7
 61       printf("%d\n",*(Array[1]));        //對2維地址進行1次解引用,得到的是一個1維地址,且與Array[1]值一樣,但Array[1]是一個2維地址
 62     10) #include<stdio.h>  
 63         #include<stdlib.h>  
 64         int main()  
 65         {  
 66 
 67             //下面是存在著非法讀寫的演示,雖然非法讀寫是可以實現,但是這只能存在於同一個進程裡面,而且這種情況沒有什麼有利的實際意義
 68 
 69             int *p;    //int類型指針,操作4個字節
 70             p=(int *)malloc(2);  //向堆區域存儲空間申請了2個字節,但不進行初始化,calloc方式的申請會進行初始化
 71             if(p)  
 72                 printf("Memory Allocated at: %p\n",p);  
 73             else  
 74                 printf("Not Enough Memory!\n");
 75             printf("%x\n",*p);     //由於只申請了2個字節,所以非法讀取了2個字節
 76             *p=0x12345678;        //由於只申請了2個字節,所以非法寫入了2個字節
 77             printf("%x\n",*p);    //由於只申請了2個字節,所以非法讀取了2個字節     
 78             free(p);   //釋放堆中申請過的2個字節,並且有可能把內存中的值也清0,這要取決於運行的內核
 79             //下面是非法讀寫了4個字節
 80             printf("%x\n",*p);    
 81             *p=0x87654321;
 82             printf("%x\n",*p);    
 83             return 0;  
 84         } 
 85     11)經探究發現,不同類型的指針指向的地址跟指針類型不一致時,有可能會報錯,也有可能只是警告而已
 86     12)unsigned char (*q)();  //聲明一個函數指針
 87        指針形式調用函數時不給定傳遞參數值的話,默認是傳遞-1   ,  指針調用函數的格式為:"(*指針名)(形參列表)" 或 "指針名(形參列表)"
 88     13)一級和多級指針的使用:
 89     int val=0x1122;
 90     char *p3=&val;
 91     char **p2=&p3;
 92 
 93     printf("%x\n", p3); 
 94     printf("%x\n", p3+1); //跳轉1個地址(因為p3是個一級指針而且類型修飾符為char)
 95 
 96     printf("%x\n", *(p3)); //操作1個字節(因為p3是個一級指針而且類型修飾符為char)
 97     printf("%x\n", *(p3+1));//操作1個字節(因為p3是個一級指針而且類型修飾符為char)
 98 
 99     printf("%x\n", (p2)); 
100     printf("%x\n", (p2+1)); //跳轉4個地址(因為內存中字節所使用的地址長度為32位且指針p2是一個二級指針)
101 
102     printf("%x\n", *(p2)); //操作4個字節(因為內存中字節所使用的地址長度為32位且指針p2是一個二級指針)
103     14)對多級多維指針的探究:
104     //假設已經掌握對多級一維指針,和一級多維指針的使用
105 
106     unsigned char (**p)[3];
107     int Array3[10]={0x804a0e0,0x55667788,2,3,4,5,6,7,8,9};  //之所以第一個元素為0x804a0e0,是因為該值取的不當,下面對(*(*p))進行解引用的時候,有可能在程序執行時導致內核塌陷,看起來好像是程序語法錯誤,也就是說要保證解引用的指針是在正確范圍內的
108     p=Array3;
109 
110     printf("%x\n", p);  //p是一個二級二維指針,指向一個二級二維地址
111     printf("%x\n", p+1);  //發生4個地址的跳轉(因為地址長度為4個字節),因為(p+1)是一個二級二維地址,也就是此行語句輸出值比上一行語句大4
112 
113     printf("%x\n", *p);   //解引用得到4個字節的值,因為p是一個二級二維指針。*p 為一級二維指針
114     printf("%x\n", (*p+1));  //跳轉3個字節,因為 *p 屬於一級二維指針,也就是此行語句輸出值比上一行語句大3。因為一級指針地址的跳轉,是取決於維數,*p是一個一級二維指針,那麼跳轉數為:sizeof(unsigned char)*[3]=3
115     
116     printf("%x\n", *(*p));  //對一級二維指針(*p)進行解引用,得到一級一維指針*(*p),該行語句打印值等效於一級二維指針*p
117 
118     printf("%d\n", *(*(*p))); //對一級一維指針*(*p)進行解引用,得到1個字節的值,值為0xe0也就是224,因為指針 p 的類型修飾符為char,而sizeof(unsigned char)=1
119 
120     printf("%d\n", *(*(*p))+1); //該行打印值比上一行大1,為225
121 
122     //總結:對多級多維指針進行解引用的時,每次解引用都會遵循先降級再降維,當級數沒降到1,那麼維數不起作用,也就是把指針當做多級一維指針來處理。
123     //        當已經是一級指針了後,維數起作用,當做一級多維指針或一級一維指針處理   
124     
125 
126 
127 ------------------------------------------*/

 

這是我對指針學習的歸納記載,如有疑問歡迎聯系作者本人一起探討~

尊重作者的勞動,轉載請記得注明來源:http://www.cnblogs.com/weifeng727/p/5584151.html

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved