G ++错误:'<anonymous>'的类型不完整

ezp*_*sso 6 gcc typedef g++ 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
);

...
Run Code Online (Sandbox Code Playgroud)

问题是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}’
Run Code Online (Sandbox Code Playgroud)

如果不改变'sense.h'包含文件以使我的项目用g ++编译,我能做些什么吗?

更新1

我发现C++标准核心语言已关闭问题第30修订版第18节规定:

如果parameter-declaration-clause为空,则该函数不带参数.参数列表(void)等效于空参数列表.

是否可以使用typedef为void而不是参数列表中的void类型?

理由:IS已经很清楚,这是不允许的.

Kei*_*son 7

快速摘要:代码是无效的C++,虽然它是否应该是一些缺乏明确性.使用void而不是VOID仅使用空括号将避免错误.

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

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

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

int foo();
Run Code Online (Sandbox Code Playgroud)

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

int bar(void);
Run Code Online (Sandbox Code Playgroud)

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])的最新草案中的相关描述:

参数声明子句确定可指定的参数,以及它们的处理中,当调用该函数时.[...]如果parameter-declaration-clause为空,则该函数不带参数.参数列表(void)等同于空参数列表.除了这种特殊情况,void不应该是参数类型(尽管类型派生自void,例如void*,可以).

这意味着void关键字in int bar(void);确实引用了类型void. 由于typedef名称是命名类型的同义词,因此int bar(VOID);应该是同等合法的. 对于类似于VOID被接受的typedef名称来说,最有意义的是void,但标准的措辞实际上是指关键字void,而不是类型.

允许的全部目的(void)是C兼容性.只是为了增加混淆,1990 ISO C标准需要void关键字; 1999和2011 C标准改变了措辞,允许使用typedef.对C++缺陷报告#577的响应确认当前的措辞需要void关键字,并提出允许typedef的更改 - 但该更改尚未在任何ISO C++标准中.它可能会出现在C++ 2011的第一个技术勘误表中.

感谢another.anon.coward查找现有的gcc错误报告.我添加了一个过于冗长的注释,表明代码是有效的,不应该生成错误消息 - 以及稍后的注释,承认代码无效,但是警告比致命错误更合适.

在此期间,我建议您联系此sense4.h头文件的提供者.如果他们#include只想从C代码中获取它,那么它就没有真正的问题(除了恕我直言的糟糕风格); 否则,他们可能会考虑使用C语言和C++ #ifdef __cplusplus语句来声明函数.你可以继续自己做出改变.无论g ++是否应该接受代码,只需进行一些更改,它就是有效的C,有效的C++,gcc和g ++都可以接受,以及更好的风格.(void)()

如果你已经阅读了这篇文章并且你仍然清醒,我印象深刻.