C語言指針與數組的區別(1) extern

近日閱讀c專家編程,對c語言中的指針數組的區別有了新的認識。

先看一段代碼:

//des.c
int a[] = {3,2};
void hello(){    
printf("d.c %d",a);
}

//test.c
#include<stdio.h>
extern void hello();
extern int *a;
int main(void){    
    hello();    
    printf("\n : %d",a);
    //printf("\n : %d",a[1]);    
    return EXIT_SUCCESS;
}

上面的代碼的輸出爲 

d.c 134520856  
: 3

第一行代碼是第一個文件d.c輸出了int a[];a的內容

第二行代碼是第二個文件hello.c輸出了extern int *a;指針a的內容

gcc編譯的時候,在鏈接階段了,hello.o有extern a符號,在d.o中找到,所以extern a 和d.o的a是同一個符號(我認爲稱他們“指向相同”有歧義)

也可以用圖像表示

。數組第一項在內存地址134520856處。

第一個文件d.c將a當成數組來處理,可以按照想象的進行輸出,但是

但是第二個文件是把符號a當成指針來操作的(因爲 extern int *a), 指針所在的地址是134520856,但是指針的值是3

如果去掉註釋之後,則會報錯,因爲在main函數中,按照編譯器的規矩,a[1]可以被我們這樣認爲 *(a+1);

因爲a等於3,a+1等於4,*(a+1)的意思就是取內存地址爲4的字節內容,我不知道地址爲4的那個字節裏面是什麼東西。

 

再看下面代碼:

int *a;
void hello(){    
     a =(int *) malloc(2);    
     a[0]=3;    
     a[1]=2;    
     printf("d.c %d",a);
     }


 

extern void hello();
extern int *a;
int main(void){    
    hello();    
    printf("\n : %d",a);    
    return EXIT_SUCCESS;
    }


輸出結果:

d.c 161968136
: 161968136

我說了實際上 只要是extern a就表示這兩個a符號,實際上是同一個符號a,(你可以將兩個文件的函數輸出&a,就會發現他們的地址是一樣的)。

這種情況下的內存分配是這樣的。

最後再看一個代碼:

int *a;void hello(){    
    a =(int *) malloc(2);    
    a[0]=3;    
    a[1]=2;    
    printf("d.c value:%d\n",a);    
    printf("d.c address:%d\n",&a);
    }


 

extern void hello();
extern int a[];
int main(void){    
    hello();    
    printf("hello.c value:%d\n",a);    
    printf("hello.c address:%d\n",&a);    
    printf("hello.c  a[1]",a[1]);    
    return EXIT_SUCCESS;
    }


 

輸出結果爲:

d.c value:160223240
d.c address:134520864
hello.c value:134520864
hello.c address:134520864
hello.c a[1]

內存分佈圖爲:

在hello.c中,a被當成int a[];

a的值爲160223240, *(a+1),就能夠訪問到2.

 

總結:

編譯器在編譯的時候左值會由編譯器分配地址,而右值運行時才能知道,當我們聲明一個指針變量的時候,會首先爲指針變量開闢一個內存空間,

即指針地址是確定的,但是指針所指向的地方時在運行時才知道。如果使用指針引用定義數組中的元素時,會將數組元素的值解析成地址,就造成了

訪問錯誤

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