這篇文章是關于理解兩段 C 代碼中的細節。為什么這樣可以:
typedef struct _api_t api_t;
typedef void (*api_set) (api_t * api;
int a;
);
typedef int (*api_read) (api_t * api;
);
struct _api_t
{
api_set set;
api_read read;
};
這不是
typedef struct _api_t
{
api_set set;
api_read read;
}
api_t;
typedef void (*api_set) (api_t * api;
int a;
);
typedef int (*api_read) (api_t * api;
);
錯誤:未知型別名稱“api_set”,錯誤:未知型別名稱“api_read”
uj5u.com熱心網友回復:
這些記錄
typedef void (*api_set) (api_t * api;
int a;
);
typedef int (*api_read) (api_t * api;
);
不正確。編譯器應該發出錯誤訊息。
看來您的意思是以下代碼
typedef struct _api_t api_t;
typedef void (*api_set) (api_t * api, int a );
typedef int (*api_read) (api_t * api );
struct _api_t
{
api_set set;
api_read read;
};
此代碼是正確的,因為在此結構定義中
struct _api_t
{
api_set set;
api_read read;
};
名稱api_set和api_read(在前面的 typedef 中定義為函式指標)在結構定義中使用之前已經定義。
至于第二個代碼片段中的結構定義,則結構定義中的名稱api_set和api_read使用尚未定義
typedef struct _api_t
{
api_set set;
api_read read;
}
api_t;
因此編譯器將發出這些名稱未定義的錯誤訊息。
uj5u.com熱心網友回復:
關于分號作為函式引數的分隔符:
typedef void (*api_set) (api_t * api; int a;);
這意外地“起作用”,因為 GCC 擴展允許函式引數的前向宣告。如果你在“pedantic”模式下運行編譯,你會看到警告:
warning: ISO C forbids forward parameter declarations [-Wpedantic]
引數的前向宣告對于將可變長度陣列 (VLAa) 作為引數的函式很有用,因為它允許在陣列引數之后傳遞陣列大小的引數。
- 沒有前向宣告
void foo(int n, int arr[static n]);
// calling example
int A[3];
foo(3, A);
- 帶前向宣告
void foo(int n; int arr[static n], int n);
// calling example
int A[3];
foo(A, 3);
此功能是向即將推出的 C23 提出的。見https://www9.open-std.org/JTC1/SC22/WG14/www/docs/n2780.pdf
在您的代碼中,這兩個引數api和a是前向宣告的,但從未實際使用過。結果,這些前向宣告被忽略,完整宣告相當于:
typedef void (*api_set) ();
其中一個指向函式的指標采用未指定數量的引數并回傳void. 可以使用任意數量的引數呼叫此函式,而不會從編譯器引發警告。此外,這種型別是不完整的,因為它與任何void獨立于使用的引數的數量和型別回傳的函式兼容。
要解決此問題,請使用,分隔符:
typedef void (*api_set) (api_t *api, int a);
此外,考慮為函式型別而不是函式指標創建別名。它通常會產生清晰的代碼:
typedef struct _api_t api_t;
typedef void api_set_f (api_t *, int);
typedef int api_read_f (api_t *);
struct _api_t {
// declare *pointer* to functions
api_set_f* set;
api_read_f* read;
};
在第二個例子中,結構struct _api_t包含一個 type 的成員api_set,但是在這個決議階段沒有定義這個型別。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/487801.html
上一篇:使用位掩碼從十進制轉換為基數4
下一篇:對術語“執行緒”的理解
