1.指針賦值
這種賦值方式是錯誤的 :
int *a;
*a=1;
這種賦值方式纔是對的
int *a;
int b=10;l
a=&b;
以上表明:a是一個指針,指向一個int大小的存儲空間,而*a表示該空間的內容,如果要想 改變*a的值,只能通過a來完成,不能直接給*a賦值。
指針a是可以賦值給內存地址比如 a=0x123456,表示,將內存地址123456賦值給int *a,而&b是不能賦值的,這樣的賦值:&b=0x123456就是錯誤的方式,因爲,&b不是一個變量,而是一個地址引用,所以不能直接賦值,而a是一個地址指針變量,可以直接賦值
在a沒有被使用的時候,它的值we爲nil(空),這也就是在stat函數中使用下面方法會報錯的原因:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc,char *argv[]){
struct stat buf; //以這種方式創建的變量,在創建的時候就已經分配內存了
if(argc<2){
printf("./s filename\n");
exit(1);
}
//f(stat(argv[1],*buf)){//這裏是以struct stat *buf創建的 *buf,在創建完成後是沒有分配內存,值是nil,則會報錯 bad address,也就是說,buf地址是空的或者是無效的
f(stat(argv[1],&buf)){ //以
struct stat buf; 這種方式創建的變量,在創建的時候就已經分配內存了
perror("stat");
printf("%s\t%s\t\n",argv[0],argv[1]);
exit(1);
}
printf("%s\t%s\t%ld\n",argv[0],argv[1],buf.st_size);
return 0;
}
在上面的代碼中 報錯bad address 的原因:
傳遞了無效的或者空的地址
所以,使用&buf不會報錯而是用*buf就會報錯bad address
2.二級指針
2.1關於main函數參數形式 char *avgv[] & char **argv
獲取參數可以通過:argv[0] argv[1] 兩種形式是定義了指針數組,每一個指針指向一個字符串指針,也就是&argv[i]得到的就是每個指針的地址,argv[i]指向的就是每個字符串
2.1理解一下int**p & char **p
首先p是一個指向一個指針地址(*P)的指針,*p指向一個實際的空間,*p是一個地址,指向一塊已經分配了或者即將要分配大小的內存空間,這個內存空間的大小的值是保存在內存中的,和指針本身沒有關係,p只是一個指向包含該內存起始地址的指針,舉個栗子:
int a[2][4]={1,2,3,4,5,6,7,8};//對於二維數組,首次要明白一個概念,就算是二維數組在內存中也是以一維的形式存儲的,所以,對於二位數組的操作使用一級指針就可以了
下面這種寫法就是錯誤的:
int **p;
p=a;//二級指針指向數組a
printf("%d",(*p)[7]);
會報錯,段錯誤(核心已轉移),所以,只有指針變量可以進行地址加減或者[]操作,也就是隻能對p[]進行這種操作
當使用printf("%d",*p);輸出的結果是 1 而是用printf("p[0]=%d p[1]=%d",p[0],p[1]);輸出的結果是:p[0]=1 p[1]=3這是因爲:
當使用二級指針指向一個數組的時候,對於64位機來說,一個指針變量的大小爲8個字節,其實*p指向的就是數組a的a[0][1] a[0][2]兩個空間,因爲一個整型佔32位,而並不是一個地址,但是在輸出的時候,自動截斷高位,只輸出低32位,對於p[0]來說,也就是輸出1,因爲2已經丟失了(猜測)。使用**p的時候,會報錯:段錯誤,因爲**p沒有任何意義,*p裏面存的也不是地址,所以,找不到。
使用p[0]輸出的時候會自動找到的是*p裏面的內容,而不是**p裏面的內容,這是指針的特性,和一級指針一樣
int *q;
int b[3]={1,2,3};
q=b;
當使用p[0]的時候,就會找到*p的內容一樣,但是這裏需要注意的是(在上面已經提過一次):如果*p裏面存的是地址,不能直接對*p進行類似指針一樣的操作比如 *p[1] 或者(*p)++ ,只有對指針變量才能進行這樣的(p[0]/p++)運算
2.3所以對於char **p來說,p[0]指向的是第一個字符串的首地址,p[1]指向的就是第二個字符串的首地址,比如對於main函數裏面使用的char **argc 參數項,我猜測,這裏底層中還是要使用malloc()函數對每個傳進來的參數進行二級指針的 *argv進行動態的賦值
*argv =(char *)malloc(argc*sizifo(char *));//argv就成爲了指針數組
示例:
#include <stdio.h> #include <stdlib.h> #define LEN 3 void malloc_a(int **p){ *p=(int *)malloc(LEN*sizeof(int*)); } int main(void){ int *a; malloc_a(&a); a[0]=1; a[1]=2; a[2]=3; printf("a0=%d a1=%d a2=%d\n",a[0],a[1],a[2]); return 0; } |
示例分析:
int **p :p是一個二級指針也就是說,如果要給p賦值,那麼對應的也應該是一個二級指針
int *a: a是一個一級指針,那麼對a做取地址運算,也就是&a就可以得到指向int型指針a的地址了,對於&a來說,它現在就相當於一個二級指針
將&a作爲形參傳遞給malloc_a()函數,即 p=&a ,p是一個指針,*p是一個指針的地址,**p是這個指針指向的實際內容,
有*p=a,所以纔可以爲*p開闢空間,在二級指針的定義上,*p是一個地址,所佔的空間大小和指針變量是一樣的,
而**p所佔的空間就是定義變量類型所決定的了。