比如我在文件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第一個字節的值