1. extern在函數聲明中是什么意思?
它可以用作一種格式上的提示表明函數的定義可能在另一個源文件中,但在
extern int f(); 和 int f(); 之間並沒有實質的區別。
補充:extern可以置於變量或者函數前,以標示變量或者函數的定義在別的文件中,提示編譯器遇到此變量和函數時在其他模塊中尋找其定義。此外extern也可用來進行鏈接指定。也就是說extern有兩個作用:
第 一,當它與"C"一起連用時,如: extern "C" void fun(int a, int b);則告訴編譯器在編譯fun這個函數名時按着C的規則去翻譯相應的函數名而不是C++的,C++的規則在翻譯這個函數名時會把fun這個名字變得面目 全非,可能是fun@aBc_int_int#%$也可能是別的,這要看編譯器的"脾氣"了(不同的編譯器采用的方法不一樣),為什么這么做呢,因為 C++支持函數的重載;
第二,當extern不與"C"在一起修飾變量 或函數時,如在頭文件中: extern int g_Int; 它的作用就是聲明函數或全局變量的作用范圍的關鍵字,其聲明的函數和變量可以在本模塊活其他模塊中使用,記住它是一個聲明不是定義!也就是 說B模塊(編譯單元)要是引用模塊(編譯單元)A中定義的全局變量或函數時,它只要包含A模塊的頭文件即可,在編譯階段,模塊B雖然找不到該函數或變量, 但它不會報錯,它會在連接時從模塊A生成的目標代碼中找到此函數。
2. 怎樣建立和理解非常復雜的聲明?例如定義一個包含N個指向返回指向字符的指針的函數的指針的數組?
這個問題至少有以下3種答案:
(1)char *(*(*a[N])())();
(2)用typedef逐步完成聲明:
typedef char *pc; /* 字符指針 */ typedef pc fpc(); /* 返回字符指針的函數 */ typedef fpc *pfpc; /* 上面函數的指針 */ typedef pfpc fpfpc(); /* 返回函數指針的函數 */ typedef fpfpc *pfpfpc; /* 上面函數的指針 */ pfpfpc a[N]; /* 上面指針的數組 */
(3)使用cdecl程序,它可以把英文翻譯成C或者把C翻譯成英文:
通過類型轉換,cdecl也可以用於解釋復雜的聲明,指出參數應該進入哪一對括號(如同在上述的復雜函數定義中)。
補充:cdecl程序非常有用,它可以在C語言的聲明和英語之間進行轉換。它可以解釋一個現存的C語言聲明,cdecl 程序可以幫助你分析復雜的聲明。
這里有一個在線的cdecl:一個在線的cdecl.
3. 為什么struct x { ... }; x thestruct; 不對?
C不是C++。結構標簽不能自動生成類型。
補充:也就是在C++中這樣是對的。在C中不想用struct只能借助於typedef。
4. NULL可以確保是0,但空指針(null)卻不一定。
5. 數組和指針的區別是什么?
如果你向函數傳遞二維數組:
在第一個聲明中,編譯器進行了通常的從“數組的數組”到“數組的指針”的隱式轉換;第二種形式中的指針定義顯而易見。
char *str; gets(str); printf("%s\n", str);
改正方法:用局部變量或用malloc()分配str緩沖區。
char *itoa(int n) { char retbuf[20]; // error sprintf(retbuf, "%d", n); return retbuf; // error }
一種解決方案是把返回緩沖區聲明為靜態變量:
總結:若要返回字符串或其它集合,則返回指針必須是靜態分配的緩沖區,或者調用者傳入的緩沖區,或者用malloc()獲得的內存,但不能是局部(自動)數組。
補充:free()過后的指針也叫做“ 野指針”,建議free()過后立即將指針置為NULL,詳細原因請看“ 為什么free(re)過后re不為NULL呢?”。
p = malloc(m * n); memset(p, 0, m * n);
13. C語言中沒有提高標准的布爾類型,需要用#define或枚舉常數定義true/false。
#define Str(x) #x #define Xstr(x) Str(x) #define OP plus char *opname = Xstr(OP);
總結:在使用符號粘接操作符##連接兩個宏的值(而不是名字)時也要采用同樣的“迂回戰術”。
而memcpy()則不能提供這樣的保證,因此可以實現的更加有效率。
如果有疑問,最好使用memmvoe()。
#define isnan(x) ((x) != (x))
int x = 1; if(*(char *)&x == 1) printf("little-endian\n"); else printf("big-endian\n");
int dayofweek(int y, int m, int d) /* 0 = Sunday */ { static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; y -= m < 3; return (y + y/4 - y/100 + y/400 + t[m - 1] + d) % 7; }