【问题标题】:Incomplete type error when compiled with g++使用 g++ 编译时出现不完整类型错误
【发布时间】:2021-02-19 03:54:44
【问题描述】:

我正在尝试使用 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++ 中工作就可以了?
  • 我正在寻找在 C++ 中工作的正确方法以及为什么 C 中没有出现错误
  • 此错误是因为您编写了一个 C 程序,但试图将其编译为 C++。 C 和 C++ 是两种完全不同的语言。

标签: c++ scope declaration unions qualified-name


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    这个错误的原因是什么

    原因是嵌套在 try_main 中的联合中嵌套的 try_inner_one 在 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 更严格。

    【讨论】:

      【解决方案3】:

      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++ 拼写,因为它嵌套在里面的类型是未命名。您可以为联合类型命名,这将允许您在 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);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-08
        • 1970-01-01
        • 2012-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-22
        相关资源
        最近更新 更多