stat函數學習引申

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所佔的空間就是定義變量類型所決定的了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章