1

我正在尝试使用 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 编译

此错误的原因是什么以及如何解决此错误

谢谢

4

3 回答 3

4

C 和 C++ 有不同的作用域规则。C++ 中类型的全名 not struct try_inner_one,因为类型定义嵌套在未命名的 union 内部try_main1

如果您想编写在 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。您可以为联合类型命名,这将允许您拼写try_inner_oneC++ 中的完全限定名称。但是,该名称不是合法的 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);
}
于 2020-11-06T12:04:51.830 回答
2

看来您正在将程序编译为 C++ 程序。在这种情况下,结构中的每个声明都try_main具有此结构的范围。

所以你需要像这样声明函数

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

或者

void func( const decltype( try_main::un )::try_inner_one &o );
于 2020-11-06T12:17:26.860 回答
2

这个错误的原因是什么

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

如何解决这个问题

您可以在 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 更严格。

于 2020-11-06T12:06:26.603 回答