使用 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);
}

What is the reason for this error

原因是 try_inner_one 嵌套在 try_main 中嵌套的联合中,无法通过 C++ 中该联合之外的上下文中的非限定名称查找找到(与 C 不同)。

how to fix this

您可以在 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){

一个 cross-language 兼容的解决方案是定义彼此之外的结构,如 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 );