C語言多文件編譯時,編譯器不檢測其聲明的變量類型與定義時的類型是否匹配

比如我在文件1裏定義int c = 0x31323334;

在文件2裏聲明extern char c;   編譯器並不會報錯的。


//File: 1.c

char a[100] = {0x31, 0x32, 0x33, 0x34, 0x35};
char *b = "abcde";
int c = 0x31323334;

char* f(void)
{
    return b;
}

//File: 2.c

#include <stdio.h>
extern char *a;
extern char b[ ];
extern char c;
extern f();

int main(void)
{
    //char *d1 = (char *)(b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24));
    char *d = (char *)((unsigned char)b[0] + ((unsigned char)b[1] << 8) + \
            ((unsigned char)b[2] << 16) + ((unsigned char)b[3] << 24));

    printf("%x\n", a);
    //printf("%c\n", *a);//這裏運行會出錯:Segmentation fault (core dumped)
    printf("%x\n", f()); //"abcde"這個字串的首地址,
    printf("%x\n", d); //  d  = f();
    //printf("%x\n", d1);
//必須先將char轉換成unsigned char,因爲char參加運算時會被提升爲int型,而對於有符號型數據,
//在擴展時,高位由符號位決定,爲1則補1,爲0則補0.無符號型數據全補0
    printf("%x %x %x %x\n", b[0], b[1], b[2], b[3]);
    printf("%x %x %x %x\n", (unsigned char)b[0], (unsigned char)b[1], \
            (unsigned char)b[2], (unsigned char)b[3]);
    
    printf("%c\n", c);
    return 0;
}

運行結果:

34333231
80485d4
80485d4
ffffffd4 ffffff85 4 8
d4 85 4 8
4


雖然在文件 1 中,編譯器知道 a 是一個數組,但是在文件 2 中,編譯器並不知道這點。大多數編譯器是按文件分別編譯的,編譯器只按照本文件中聲明的類型來處理。所以,雖然 a 實際大小爲 100 個 byte,但是在文件 2 中,編譯器認爲 a 是一個char*指針,只佔 4 個 byte。編譯器會把存在指針變量中的任何數據當作地址來處理。故文件2中a存放的數據其實是文件1中數組a的前4個元素,即文件2中a=0x34333231(小端機器),對這個未定義的地址進行訪問,所以出錯了。


而文件2中,編譯器把b當作char數組了,在文件1中 b實際上是指向了"abcde"這個字串的首地址,故文件2中b數組的前四個元素爲"abcde"這個字符串的首地址,我將文件中b數組4個元素的值轉換成一個指針d,d的值與f()所返回的值相同


文件2中,編譯器將c 當做char型,c的值爲文件1中int c第一個字節的值




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