1. C和C++語言中的優先順序規則
C語言中語言聲明的優先順序規則如下(以後分析的基礎):
A 聲明從它的第一個名字開始讀取,然後按照優先順序順序依次讀取
B 優先順序從高到低依次是
B. 1 聲明中被括弧括起來的那部分
B. 2 尾碼操作符:
括弧()表示這是一個函數
方括號[]表示這是一個陣列
B. 3 首碼操作符:星號*表示“指向……的指標”
下面我們使用上述規則來分析以下例子
(1) char * const *(*next)();
(2) char* (*c[10])(int **p)
一步步分析:先分析括弧裡面的內容, 我們知道C是一個陣列, 保存的是“…..的指標”然後根據規則B, 要先分析尾碼, 得到指標是一個函數指標。 該函數參數為P返回值為char*。
(3) void(*signal(int sig,void(*func)(int)))(int);
從signal所在的括弧開始提取:void(*signal( ) )(int); 首先signal尾碼跟的是括弧, 我們得到signal是一個函數, 然後得到首碼為* 表示此函數返回的是一個”……指標”…………最後得到signal是一個函數, 返回函數指標,函數所指向的指標接受一個int類型的參數並且返回void。
然後我們看signal函數參數本身: void(*func)(int) 表示func是一個函數指標, 此指標指向的函數接收一個int參數, 返回值是void。
如果我們定義typedef void(*ptr_to_func)(int)則表示 ptr_to_func是一個函數指標, 該函數接受一個int參數,返回值為void 那麼上述函數可以寫為
ptr_to_funcsignal(int sig, ptr_to_func); 表示 signal 是一個函數 , 接收參數為int和 ptr_to_func, 返回ptr_to_func ;
2. typedef int x[10]與 #define x int[10]的區別
typedef與巨集文本替換之間存在關鍵性的區別。 如下:
第一: 可以用其他類型說明符對宏名進行擴展,
#define peach int
unsigned peach i ; // 可以
typedef int banana;
unsigned banana i ; // 錯誤
第二:在連續聲明的變數中用typedef定義的類型能夠保證聲明中所有變數均同一種類型, 而用#define定義的類型卻無法保證。 如下:
#define int_ptr int*
int_ptr chalk, cheese;
經過宏擴展, 第二行變為:
int *chalk, cheese; 這使得chalk 與cheese為不同的類型。 chalk為int類型的指標, 而cheese只是int類型變數。
typedef char * char_ptr;
char_ptr Benley, Royce ; Benley,和Royce類型是相同的。 都是指向char的指標
原因: #define在編譯時僅僅是名稱替換而typedef可以被看成一個徹底封裝的“類型”。 在瞭解typedef 中變數具體表達什麼意思的時候可以按照前面說的優先順序規則進行解析。
3. 指針與typedef
typedef中使用指針往往帶來意外的結果。 例:
typedef string *pstring;
const pstring cstr;
c_str究竟代表什麼類型。 我們知道pstring是指向string的指標很多人都會誤認為真正的類型是const string* cstr。 錯誤原因是將typedef當成#define 直接進行文本擴展了,
string *const cstr;