簡體   English   中英

使用 g++ 編譯時類型不完整錯誤

[英]Incomplete type error when compiled with g++

我正在嘗試使用 g++ 執行以下代碼並收到不完整的類型錯誤

#include <stdio.h>
struct try_main{
  union{
    struct try_inner_one{
      int fl;
      float g;
    }one;
    struct try_inner_two{
      char a;
    }two;
  }un;
  int chk;
};

void func(struct try_inner_one o){
  printf("%d\n",o.fl);
}
int main(){
  struct try_main z = {{1,2},3};
  func(z.un.one);
return 0; 
}

錯誤:

union.c: In function ‘void func(try_inner_one)’:
union.c:15:6: error: ‘o’ has incomplete type
 void func(struct try_inner_one o){
      ^
union.c:15:18: error: forward declaration of ‘struct try_inner_one’
 void func(struct try_inner_one o){
                  ^
union.c: In function ‘int main()’:
union.c:20:16: error: parameter 1 of ‘void func(try_inner_one)’ has incomplete type ‘try_inner_one’
   func(z.un.one);

上面的代碼用gcc成功編譯

此錯誤的原因是什么以及如何解決此問題

謝謝

C 和 C++ 具有不同的范圍規則。 C++ 中類型的全名不是struct try_inner_one ,因為類型定義嵌套在try_main內的未命名聯合中。 1

如果您想編寫在 C 和 C++ 中同樣有效的代碼,請將類型定義拉到頂層:

struct try_inner_one {
  int fl;
  float g;
};

struct try_inner_two {
  char a;
};

struct try_main {
  union {
    struct try_inner_one one;
    struct try_inner_two two;
  } un;
  int chk;
};

1這種類型的完全限定名稱不能在 C++ 中拼寫,因為它嵌套在其中的類型是unnamed 您可以為聯合類型命名,這將允許您在 C++ 中拼寫try_inner_one的完全限定名稱。 但是,該名稱不是合法的 C 代碼,因為 C 沒有范圍解析運算符。

如果您想保留嵌套類型定義,您可以為聯合命名(在下文中為union_name )並執行以下操作以保持代碼為 C 和 C++ 編譯:

// (Type definition omitted.)

#ifdef __cplusplus
using try_inner_one = try_main::union_name::try_inner_one;
#else
typedef struct try_inner_one try_inner_one;
#endif

void func(try_inner_one o){
  printf("%d\n", o.fl);
}

這個錯誤的原因是什么

原因是嵌套在try_inner_one中的聯合中的try_main無法通過 C++ 中該聯合之外的上下文中的非限定名稱查找找到(與 C 中不同)。

如何解決這個問題

您可以在 C++ 中使用限定名稱:

void func(decltype(try_main::un)::try_inner_one o){

如果您為聯合命名,則可以簡化:

union u { // note the name
    struct try_inner_one{

void func(try_main::u::try_inner_one o){

跨語言兼容的解決方案是在彼此之外定義結構,如 Kondrad Rudolph 的回答中所述。


一個警告:在如何訪問聯合的非活動成員方面,C++ 比 C 更嚴格。

您似乎正在將程序編譯為 C++ 程序。 在這種情況下,結構try_main中的每個聲明都具有該結構的作用域。

所以你需要像這樣聲明函數

void func( decltype( try_main::un )::try_inner_one o );

或者

void func( const decltype( try_main::un )::try_inner_one &o );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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