![](/img/trans.png)
[英]How do you call a C function that takes (or returns) a struct by value from JS via Emscripen/Wasm?
[英]How do I call a function that takes an anonymous struct in C?
如何調用在 C 中采用匿名結構的 function?
比如這個function
void func(struct { int x; } p)
{
printf("%i\n", p.x);
}
盡管對某些應用程序有用,但不能在 C 中單獨將裸露的匿名結構作為 function 參數傳遞。 它需要一些幫助,例如 typedef 句柄或作為命名結構的成員。
匿名結構本身:
struct {
int x;
};
作為 function 參數導致警告:
“預期為‘struct’,但參數的類型為‘struct’void func(struct {int x;}p)”
(@Eugene Sh 指出)
幫助 Typedef:
typedef struct
{
int x;
}anon_s;
void func(anon_s *p)
{
printf("%i\n", p->x);
}
int main(void)
{
anon_s anon = {10};
func(&anon);
return 0;
}
或者,由具有名稱或類型定義的代理攜帶:
struct anon{
// Anonymous struct
struct
{
int x;
};
};
When a function declaration that provides a prototype is in scope, the arguments to calls to that function must be have types compatible with those declared in the prototype, where "compatible" has a specific meaning defined by the standard:
如果它們的類型相同,則兩種類型具有兼容的類型。 確定兩種類型是否兼容的附加規則[與相關案例無關]。 此外,如果它們的標記和成員滿足以下要求,則在單獨的翻譯單元中聲明的兩種結構、聯合或枚舉類型是兼容的:如果用標記聲明一個,則另一個應用相同的標記聲明。 如果兩者都在各自翻譯單元內的任何地方完成,則適用以下附加要求:它們的成員之間應存在一一對應關系,使得每對對應的成員都聲明為兼容類型; [...] 並且如果該對中的一個成員聲明了一個名稱,則另一個成員聲明為相同的名稱。 對於兩個結構,相應的成員應以相同的順序聲明。 [...]
(C11, 6.2.7/1)
Being "the same type" in the sense meant by the standard is a matter of scope, and there is no way for a caller of your function to satisfy that because the scope of the structure declaration in a function parameter list is restricted to the function它出現在其中的定義(如果有),或者如果它只出現在原型中,則單獨出現在參數列表中。
然后,要調用 function,您必須以某種方式利用額外的類型兼容性規則,這些規則僅適用於(僅)在與調用者不同的翻譯單元中定義func()
時。 在這種情況下,最簡單的做法可能是在調用者的翻譯單元中typdef
一個兼容類型:
typedef struct { int i; } one_int;
然后,您將在該 TU 中對 function 進行原型設計:
void func(one_int p);
你會用one_int
類型的參數調用它。 例如,
one_int oi = { 1 };
func(oi);
但是請注意,盡管上述原型與問題中給出的 function 定義兼容,只要它們出現在不同的翻譯單元中,兩者就不能出現在同一個翻譯單元中,因此您不能遵循通常的建議。 c 文件#include
聲明其功能的標頭。
總的來說,最好將結構聲明從原型中取出,或者借助上面演示的typedef
,或者給它一個標簽,其中任何一個都可以從代碼中引用它從它的定義。
如果您在啟用警告的情況下編譯程序,您將收到類似的警告
warning: anonymous struct declared inside parameter list will not be visible outside of this definition or declaration
void func(struct { int x; } p)
^~~~~~
因此,您需要為記錄命名並在 function 聲明中使用此名稱,例如
typedef struct {
int x;
} T;
void func(T p)
{
printf("%i\n", p.x);
}
首先,您沒有匿名結構。 你有一個未命名的結構。 匿名結構的概念在 C 中具有特定的語義。
您不能調用 function,因為即使將命名的結構類型在 function 塊 scope 之外也不可見。
您需要在 function 參數列表之外聲明結構,並使用 typedef 為其分配名稱或別名。
由於匿名結構的類型僅在func()
的主體中可見,您可以使用它來遞歸調用func()
。
void func(struct { int x; } p)
{
printf("x=%d\n", p.x);
func(p);
}
除了其他答案中提到的警告外,代碼編譯得很好。
因此理論上可以使用匿名結構作為參數調用 function。 最初的電話是一個挑戰。 我認為沒有任何可移植的方式來調用初始調用。 可能通過將指針func()
轉換為其他類型的 function 指針來實現,該指針對於給定的實現是二進制兼容的。
void func(struct { int x; } p)
{
printf("x=%d\n", p.x);
if (p.x --> 0)
func(p);
}
int main() {
// call through a pointer to function with unspecified number of arguments.
void (*func_p)() = func;
struct almost_p { int x; } p = { 10 };
func_p(p);
return 0;
}
Ii 在我的機器上工作得很好,但它是不可移植的,並且可能由於struct {...}
和struct almost_p
不兼容而觸發 UB。
但是,如果參數是指向匿名結構的指針,那么情況看起來更有希望。
void func(struct { int x; } *p);
可以將初始調用設為func(NULL)
。 在func
中,實際的p
object 可以用calloc()
構造。 之后,您可以遞歸調用它func()
或將實例p
存儲在void*
類型的全局變量中。
例子:
void func(struct { int x; } *p) {
if (!p) p = calloc(1, sizeof *p);
printf("x=%d\n", p->x);
if (p->x++ < 10)
func(p);
}
int main() {
func(NULL);
return 0;
}
它編譯良好並輸出:
x=0
x=1
x=2
x=3
x=4
x=5
x=6
x=7
x=8
x=9
x=10
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.