我正在學習 C99 - 函式指標部分,我的教科書提供了一種使用“typedef”來簡化以下代碼的方法:
int (*p[4])(int,int) = {&Sum,&Sub,&Mul,&Div};
↓
typedef int (*OP_TYPE)(int,int);
OP_TYPE p[4]={&Sum,&Sub,&Mul,&Div};
我知道'typedef'只能這樣使用:例如。
typedef unsigned short int US;
是不是錯了,int會改成(*OP_TYPE)(int,int),難道不是對的第二句變成(*OP_TYPE)(int,int)(*p[4])(int,int) = {&Sum,&Sub,&Mul,&Div};
我不明白為什么第二句話會這樣。
uj5u.com熱心網友回復:
除了初始化部分之外,typedef關鍵字在語法上的行為類似于存盤修飾符(即auto,等)。我猜這是因為早期版本的 C 編譯器在變數宣告和型別別名宣告之間共享代碼。registerstatic
因此型別別名宣告和變數宣告看起來或多或少相同:
static int (*A[4])(int,int); // staic variable
typedef int (*B[4])(int,int); // type alias
int (*C[4])(int,int); // local variable
我想問題是為什么一個人不能這樣做:
int (*[4])(int,int) C;
我對此沒有很好的答案,C 語法就是這樣定義的。我可以猜測,如果沒有錨,編譯器將無法正確決議型別。
那么為什么不能這樣做:
(int (*[4])(int,int)) C;
回答:
它將解決缺少錨的問題。但是,它不能使用,因為它會與強制轉換運算子沖突(type) expr。請注意,符號C可能會在范圍外定義,從而導致歧義。
int C;
{
// cast `C` to `int*` or maybe declare a pointer to `int`
(int*)C;
}
但是,有一個typeof擴展的解決方法(即將到來的 C23 中的一個功能)。
typeof(int (*[4])(int,int)) C;
這或多或少與編譯器擴展以下宣告的方式相同:
typedef int (*OP_TYPE)(int,int);
OP_TYPE p[4]={&Sum,&Sub,&Mul,&Div};
to
typeof(int(*)(int,int)) p[4] = { ... }
此外,使用這個技巧可以對復雜型別進行簡潔易讀的宣告。
typeof(int(int,int))* p[4] = { .... }
很容易看出這是一個 4 元素的函式p指標陣列。int(int,int)
uj5u.com熱心網友回復:
是不是錯了,
int會改成(*OP_TYPE)(int,int),難道不是對的第二句變成(*OP_TYPE)(int,int)(*p[4])(int,int) = {&Sum,&Sub,&Mul,&Div};
宣言
typedef int (*OP_TYPE)(int, int);
不改變的意思int——它改變了的意思OP_TYPE。
首先,一些背景:
C 中的宣告分為兩個主要部分:宣告說明符序列,后面是逗號分隔的宣告符串列。
宣告器介紹被宣告事物的名稱,以及有關該事物的陣列、函式和指標的資訊。在 typedef 中,該名稱成為該型別的別名。
宣告器的結構旨在反映代碼中運算式的結構。例如,假設您有一個arr指標陣列,int并且您想要訪問第i'th 元素指向的整數物件;您將索引到陣列并取消參考結果,如下所示:
printf( "%d\n", *arr[i] ); // *arr[i] is parsed as *(arr[i])
運算式 的型別*arr[i]是int; 這就是為什么我們把它的宣告寫成
int *arr[N];
代替
int *[N] arr;
在運算式中,后綴[]下標運算子arr的運算元是 ,一元*解參考運算子的運算元是運算式arr[i]。這些運算子在宣告中遵循相同的優先規則,因此是上述宣告的結構。
宣告內容如下
arr -- arr
arr[N] -- is an array of
*arr[N] -- pointer to
int *arr[N]; -- int
因此,命名物件arr的型別為“指標陣列int”;
類似地,如果你有一個函式指標陣列并且你想呼叫其中一個函式,你可以索引到陣列中,取消參考結果,然后用任何引數呼叫結果函式:
x = (*p[i])(a, b);
同樣,運算式 的型別(*p[i])(a, b)是int,因此可以得出 的宣告p
int (*p[4])(int, int);
并不是
int (*[4])(int, int) p;
同樣,宣告內容為
p -- p
p[4] -- is a 4-element array of
*p[4] -- pointer to
(*p[4])( ) -- function taking
(*p[4])( , ) -- unnamed parameter
(*p[4])(int, ) -- is an int
(*p[4])(int, ) -- unnamed parameter
(*p[4])(int, int) -- is an int
int (*p[4])(int, int); -- returning int
所以命名的物件p的型別是“陣列指標,指向帶有兩個int引數并回傳的函式int”。
到目前為止清楚嗎?
那么,如何typedef影響這一點呢?
讓我們從沒有的宣告開始typedef:
int (*OP_TYPE)(int, int);
這宣告OP_TYPE為一個型別為“指向帶有兩個引數并回傳的函式的指標”的物件。如果我們添加關鍵字:intinttypedef
typedef int (*OP_TYPE)(int, int);
它改變了宣告的含義,使其成為“指向函式的指標,采用兩個引數并回傳”型別OP_TYPE的別名。它根本不會改變宣告的結構,只會改變含義。因此,你可以寫intint
OP_TYPE fp;
它的含義與
int (*fp)(int, int);
其他一些例子可能有助于推動這個概念。回到前面的例子,如果
int *ap[N];
宣告ap為“指向指標的 4 元素陣列”型別的物件int,然后
typedef int *ap[N];
宣告ap為“指向指標的 4 元素陣列”型別的別名int,這樣
ap foo;
相當于
int *foo[N];
如果
int (*blah)[N];
宣告blah為“指向 N 元素陣列的指標”型別的物件int,然后宣告
typedef int (*blah)[N];
宣告blah為“指向 N 元素陣列的指標”型別的別名int。
在您提供的示例中,
unsigned short int US;
宣告US為型別的物件unsigned short int;因此,
typedef unsigned short int US;
宣告US為型別的別名unsigned short int。
宣告(因此typedefs)可以變得任意復雜:
int *(*(*foo())[N])(double);
foo是一個指向函式的指標,它回傳一個指向函式的指標陣列的指標,該函式接受一個double引數并回傳一個指向int. 添加一個typedef:
typedef int *(*(*foo())[N])(double);
更改foo為型別“函式回傳指向函式指標陣列的指標的別名,該指標指向接受double引數的函式并回傳指向int; 的指標,
foo bar;
相當于寫
int *(*(*bar())[N])(double);
uj5u.com熱心網友回復:
int不會被typedef. typedef unsigned short int US;不是“改變” unsigned short int,而是定義識別符號US以表示與unsigned short int. 同樣,typedef int (*OP_TYPE)(int,int)定義識別符號OP_TYPE以表示與int (*)(int, int)(指向回傳int引數型別串列的函式的指標int, int)相同的型別。
從語法上講,typedef它就像一個存盤類說明符,但它定義了一個“typedef name”而不是宣告一個變數。比較。typedef int (*OP_TYPE)(int, int);_ 是一個 typedef 名稱并且是一個變數。并且兩者都具有相同的型別。可以在后續宣告中用作型別,因此等價于static int (*op)(int, int);OP_TYPEopOP_TYPEopint (*)(int, int)OP_TYPEstatic OP_TYPE op;static int (*op)(int, int);
uj5u.com熱心網友回復:
歡迎來到stackoverflow @moveityourself01!
OP_TYPE 是函式指標型別。這是一個例子:
// This is a function
// It has a single parameter and returns
// an int
int some_func(int a) {
return(a 1);
}
int main(void) {
// regular usage of the function
printf("some_func(1) = %d\n", some_func(1));
// fun_ptr is a function pointer
// that points to the function some_func
int (*fun_ptr)(int) = &some_func;
printf("via fun_ptr->some_func(2) = %d\n", fun_ptr(2));
// create the typedef
typedef int (*funptr_type)(int);
// usage of typedef
funptr_type another_func_ptr = &some_func;
// usage of function pointer via typedef
printf("via typedef some_func(3) = %d\n", another_func_ptr(3));
return(0);
}
用法
some_func(1) = 2
via fun_ptr->some_func(2) = 3
via typedef some_func(3) = 4
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/484003.html
上一篇:如何為結構分配記憶體?
下一篇:*&var是多余的嗎?
