簡體   English   中英

如何調用在 C 中采用匿名結構的 function?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM