c语言基础3
指針
指針就是內存地址。通常我們說的指針是指:指針變量。
因此:指針變量存放指針,指針就是一個內存空間的地址!
int a
int *p
比較:a標示了內存的一個空間,該空間能夠存放一個整數。p是一個指針類型變量(通常稱為指針),它也標示了內存的一個空間,該空間存放的是一個內存地址(內存地址在32位下為4字節)。
理解指針:我們需要弄清指針的三方面內容
1、指針的類型
2、指針所指空間存儲數據的類型
3、指針的值及存儲指針的空間大小
以下通過例子說明這三方面:
1、int? *p;
2、char *p;
3、int **p;
4、int (*p)[3]
1、指針的類型:從語法的角度講,只要將定義中指針的名字去掉,剩下的部分就是這個指針的類型。
1、int? *p;?? int*
2、char *p; char*
3、int **p; int**
4、int (*p)[3] int(*)[3]
理解:一個基本的數據類型加上*號,就構成了指針的類型,這個類型定義的變量大小是一定的,與*號前面的數據類型無關。*號前面的數據類型只是說明了指針所指向的內存里存儲數據的類型! 如:int* 就是個指針的類型,用該類型定義的變量p大小(32位的為4個字節),int說明該指針所指向的內存里存儲的是int類型的數據!
2、指針所指空間存儲數據的類型:語法上講:只需把指針定義中的指針變量名和名字左邊的指針聲明符*去掉,剩下的就是指針所指空間存儲數據的類型。
1、int? *p;?? int
2、char *p; char
3、int **p; int*
4、int (*p)[3] int [3]
理解:指針所指空間的數據類型是我們所關心的,對于編譯器來說,根據該類型來確定讀寫從指針地址開始的多少個字節空間的數據。
3、指針的值以及存儲指針值的空間大小
指針的值是指針變量本身存儲的數值,由于指針就是一個內存地址,所以指針的值也就是一個內存地址。在32位系統中,內存地址均為32位長,所以存儲指針的空間為4個字節。可以用sizeof()來測試。
對比一般變量和指針變量的定義和含義:
int p; p是整型變量,用于標識內存的一個空間內能存放一個整數
int *p; p是指針類型變量,用于標識內存的一個內存空間內能存放一個地址,該地址處能存放一個整數
int p[5]; p是一個數組(一段連續的存儲空間),數組中有5個元素,每個元素為一個整數,p為這段連續存儲空間的首地址
int *p[5]; p是一個數組(一段連續的存儲空間),數組中有5個元素,每個元素為一個地址(類型為int *),每個地址處能存放一個整數,p為這段連續存儲空間的首 地址?????? (被成為指針數組,主體是數組,[ ]優先級高于*)
int (*p)[5]; p是一個指針類型的變量,p指向具有5個元素的數組(類型為int[5]),數組中的元素為整數。(被稱為數組指針,主體是指針!)
int **p; p是指針類型的變量,用于標識內存的一個空間能存放一個地址(類型為int**),該地址處存放的存放的還是一個地址(類型為int *),這個地址處能存放一 個整數(類型為int)
int p(int);??? p是一個函數,函數有個整型參數,并且函數返回值為整型
int (*p)(int); p是一個指針,一個指向函數的指針,函數有一個整型參數,并且函數返回值為整型。
1 #include<stdio.h>2 3 main()4 {5 int a=12,*p,**ptr;6 ptr=&p;7 p=&a;8 **ptr=34;9 printf("%d,%d,%d\n",a,*p,**ptr);10 }輸出:34,34,34
?
?
指針和數組:????????????????????? (指針和數組是不同的,指針是內存單元的一個地址32位為4字節,數組其大小和元素類型和個數有關。
對指針和數組元素的訪問,可以采用下標法,也可以采用指針法。貌似指針和數組有什么關系,事實上,它兩沒有關系。指針就是指針,數組就是數組。
在內存中的數據,一種方法是用數組名加下標的方式讀寫,另一種方法是通過指針間接的讀寫。
?1.對數組元素的訪問: int a[10]={0,1,2,3,4,5,6,7,8,9};
a為數組元素的首地址a[0],現在想讀取整數5; (1)指針法: *(a+5) (2)數組法:a[5], 編譯器把以下標形式的操作解析為以指針的形式的操作,a作為數組元素的首地址,再加上括號中5個元素的偏移量,a+5*sizeof(int)
2、對指針所指空間的訪問: char *p=“abcde”;
p為一個指針變量,大小為4個字節(32位系統),p里面存儲了一塊內存的首地址,這塊內存在靜態區(還不明白),其空間大小為6個字節,這快內存空間沒有名字,通過匿名訪問。 讀取字符d? (1)指針法:*(p+3) (2)下標法 p[3]? ,譯法和上面相同
注意:指針加減偏移量時,不是代表指針移動多少個字節,而是代表移動多少個指針所指的元素。
?
?指針和數組的聲明和定義:
外部變量的引用問題:如果在文件1中定義了一個數組,在文件2中要引用這個數組,那么在這兩個文件中怎樣聲明和定義呢?
在同一個文件中,特別是數組名作為函數參數時,實參和形參可以用數組,也可以用指針,兩種任意組合沒有問題(還沒有試過)。但是在不同文件間引用數組時,作為外部變量的聲明形式必須和另一個文件中的定義形式相同,否則會出錯,切記!!!
例子:?? file1.c 中:
1 #include<stdio.h>2 3 extern void func(void);4 char *a={"ABCDE"};5 6 void main()7 {8 func();9 printf("%c,%c\n",a[1],a[2]);10 }file2.c中:
1 #include<stdio.h>2 3 extern char *a;4 void func()5 {6 printf("%c\n",a[1]);7 }gcc -c file1.c file2.c
gcc -o file file1.o file2.o
./file
輸出: B
???? B ,C
若將 file2.c中 extern char *a;改為 extern? char a[ ]; 則上面的輸出第一行的變成亂數! why??
因為:在file2.c中將a聲明為外部數組(注意這里聲明是不分配空間的,所以無須說明數組有多少個元素,具體是多大可以在其它文件中定義)
這時編譯器認為a是一個數組,其大小為4個字節(因為file1.c中定義了a為指針變量),因此a[1]就輸出a這個指針變量中指針的第二個字節內容!是不確定的。。。
若將file1.c中 char *a={"ABCDE"}; 該為 char a[ ]={"ABCDE"} ; file2.c 中不變,則運行出現段錯誤。。。 why??
file1.c中定義數組a,并為其分配6個字符的空間,但在file2.c中,編譯器并不知道a是個數組,認為a是個指針變量,而這時候a中存的值為數組{“ABCDE“},由于指針大小為4個字節,所以在file2.c 中a的值變為{”ABCD“},該值被作為指針(畫圖好理解),這時候輸出a[1](相當于*(p+1)),這個地址中的值不確定。。可能這個地址都越界,出現段錯誤!
?
指針的算術運算和關系運算:
指針的算術運算:因為指針是一個內存地址,所以,其加減一個整數的意義是:指針從當前地址移動多少個元素,元素是指針所指空間存儲的數據類型。
1 #include<stdio.h>2 3 main()4 {5 char s[]={"ABCDEFGH"};6 int *p; 7 p=(int *)s;8 p++;//p+sizeof(int)*1,p+4,指向E9 printf("%c\n",*p); 10 p=p+5;//p+sizeof(int)*5,p+20,越界了,這里p指向的是int類型的數據11 printf("%c\n",*p);12 }輸出E和亂碼
1 #include<stdio.h>2 3 main()4 {5 char s[]={"ABCDEFG"};6 char *p,**ptr;7 p=s;8 ptr=&p;9 printf("%c\n",**ptr);10 ptr++;11 printf("%c\n",**ptr);12 }輸出A和段錯誤!
在第10行,ptr++,ptr指向的類型是char *,是個指針,大小為4字節,所以ptr=ptr+sizeof(char *)*1=ptr+4,這時候ptr的值越界了。。(畫圖好理解)
另外:關系運算,兩個指針可以進行減法運算,一般是高地址減去低地址,兩個指針不能進行加法運算是非法的!關系運算符也都適用。
?
數組的首地址和數組元素的首地址:
注:它兩值是相同的,但是類型不同,數組首地址&a;;;數組元素首地址:a或a[0],等價。。。
例子:
1 #include<stdio.h>2 3 /*該程序說明 數組首地址 和 數組首元素的地址 的區別4 *數組首元素(a==a[0])和&a值是一樣的,但是類型不同5 *a/a[0]類型是:int * 6 *&a的類型是:int(*)[]7 *也就是說下面程序中p1和p2的值是一樣的8 */9 10 11 main()12 {13 int a[10]={1,2,3,4,5,6,7,8,9,10};14 int *p1;15 int (*p2)[10]; 16 p1=a;17 p2=&a;18 printf("%d\n",*p1);19 printf("%d\n",*(int *)p2); 20 printf("%d\n",*(p1+1)); 21 printf("%d\n",*(int *)(p2+1));22 }?要是16行改為:p1=&a; 則編譯出現:
ptr1.c:16: warning: assignment from incompatible pointer type?原程序輸出:
1 1 2 -107886372821行輸出亂碼,因為p2+1, p2 的類型為 int? [10](所指向數據的類型), 那sizeof(p2)=4*10 字節了,? p2+1 =p2+ 4*10*1
轉載于:https://www.cnblogs.com/byking/archive/2013/03/14/2960419.html
總結
- 上一篇: centos虚拟机根目录空间分配
- 下一篇: 了解你所不知道的SMON功能(五):Re