gcc - G++ 错误 : ‘<anonymous>’ has incomplete type

标签 gcc g++ typedef void

我被迫使用第三方加密狗访问库,该库提供包含文件“sense4.h”,代码如下:

#if !defined _WINDOWS_

#define WINAPI
#define CONST const

typedef unsigned char   UCHAR;
typedef unsigned short  USHORT;
typedef unsigned int    UINT;
typedef unsigned long   ULONG;

typedef char            CHAR;
typedef char            TCHAR;

typedef void            VOID;

...

#endif /* !defined _WINDOWS */

...

unsigned long WINAPI S4Startup(
        VOID
);


unsigned long WINAPI S4Cleanup(
        VOID
);

...

问题是 g++ 4.6.1 提示使用 typedefed VOID 的代码行:
sense4.h:375:9: error: ‘<anonymous>’ has incomplete type
sense4.h:376:1: error: invalid use of ‘VOID {aka void}’
sense4.h:383:9: error: ‘<anonymous>’ has incomplete type
sense4.h:384:1: error: invalid use of ‘VOID {aka void}’

在不更改“sense.h”包含文件以使我的项目使用 g++ 编译的情况下,我能做些什么吗?

更新 1

我发现C++ Standard Core Language Closed Issues, Revision 30的第18节状态:

If the parameter-declaration-clause is empty, the function takes no arguments. The parameter list (void) is equivalent to the empty parameter list.

Can a typedef to void be used instead of the type void in the parameter list?

Rationale: The IS is already clear that this is not allowed.

最佳答案

快速总结:代码不是有效的 C++,尽管它是否应该是不明确的。使用 void而不是 VOID ,或者只使用空括号,将避免错误。

我认为这是 g++ 中的一个错误。

我认为这是 g++ 中的一个错误。我现在确信它不是,尽管我认为最好将此作为警告而不是 fatal error 。

通常在 C++ 中,没有参数的函数用空括号声明:

int foo();

作为对 C 兼容性的让步,C++ 还允许使用 C 风格的原型(prototype),使用 void表示该函数没有参数(因为空括号在 C 中表示其他含义):
int bar(void);

g++ 的解释似乎是 void在此语法中,这里不是指不完整类型 void ;相反,它将其视为一种特殊语法,具有独特的关键字用法。

我认为您需要修改头文件以使 g++ 接受它。

gcc 接受它为有效的 C,但如果您需要 #include,这将无济于事它来自 C++ 源文件——除非您编写 C 包装器并从 C++ 代码中调用它,这可能是可接受的解决方法。

(顺便说一句,我讨厌这样的 typedef。typedef void VOID; 的目的是什么?作者是否认为 void 太困惑了?我怀疑这是为了与不支持 void 关键字的非常旧的 C 编译器兼容,但是对此的需求早已过去。)

以下是 ISO C++ 2011 标准 (8.3.5 [dcl.fct]) 最新草案的相关描述:

The parameter-declaration-clause determines the arguments that can be specified, and their processing, when the function is called. [ ... ] If the parameter-declaration-clause is empty, the function takes no arguments. The parameter list (void) is equivalent to the empty parameter list. Except for this special case, void shall not be a parameter type (though types derived from void, such as void*, can).



这意味着 void int bar(void); 中的关键字确实指的是类型 void .由于 typedef 名称是命名类型的同义词,int bar(VOID);应该同样合法。对于像 VOID 这样的 typedef 名称最有意义。代替void被接受,但标准的措辞实际上是指关键字void ,而不是类型。

许可的全部目的(void)是 C 兼容性。更令人困惑的是,1990 ISO C 标准要求 void关键词; 1999 年和 2011 年的 C 标准改变了措辞,允许使用 typedef。对 C++ Defect Report #577 的回复确认当前措辞需要 void关键字,并提出了允许 typedef 的更改——但该更改尚未出现在任何 ISO C++ 标准中。无论何时发布,它都可能出现在 C++ 2011 的第一个技术勘误表中。

感谢 another.anon.coward用于查找现有的 gcc bug report .我添加了一个过于冗长的注释,暗示代码是有效的并且不应该产生错误消息——后来的注释承认代码是无效的,但警告比 fatal error 更合适。

同时,我建议联系这个 sense4.h 的提供者。头文件。如果他们打算 #include d 仅来自 C 代码,没有真正的问题(除了恕我直言的糟糕风格);否则,他们可能会考虑使用 #ifdef __cplusplus ,用 (void) 声明函数用 C 语言和 ()在 C++ 中。你可以继续自己做出改变。 g++ 是否应该接受该代码,只需进行一些更改,它将是有效的 C、有效的 C++、gcc 和 g++ 都可以接受的,以及更好的风格。

如果你读了这么多,你还醒着,我印象深刻。

关于gcc - G++ 错误 : ‘<anonymous>’ has incomplete type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9742135/

相关文章:

c++ - gprof - 文件缺少调用图数据

c++ - 如何从我的 Mac 上的终端窗口运行 g++

c++ - 在 C++ 中创建 Typedef

c - 某些对 "calloc"的调用速度快得令人怀疑

qt - CUDA 10 不支持高于 7 的 Gcc 版本 - Arch Linux 中的 Qt 错误

c++ - 模板类静态成员的初始化

c++ - 什么时候通过引用传递 C++ 中的重载运算符?

c++ - 模板化 vs const 非模板化 vector 没有已知的转换

c - 将 typedef 从 header 传递到源 - C

linux - 如何在 Linux 上的 CDT eclipse 中设置个人构建?