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

时间:2012-03-16 17:51:54

标签: 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条规定:

  

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

     

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

     

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

1 个答案:

答案 0 :(得分:7)

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

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

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

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

int foo();

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

int bar(void);

g ++的解释似乎是这里语法中的void没有引用不完整的类型 void;相反,它将它视为一种特殊的语法,并使用了关键字。

我认为您需要修改头文件才能让g ++接受它。

gcc接受它作为有效的C,但如果您需要从C ++源文件中#include它,这没有用 - 除非您编写C包装并从C ++代码调用它,这可能是可接受的解决方法。

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

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

  

parameter-declaration-clause 确定可以的参数   在调用函数时指定及处理它们。 [...   如果 parameter-declaration-clause 为空,则该函数采用   没有争论。参数列表(void)等同于空   参数列表。除了这种特殊情况,void不应该是   参数类型(虽然派生自void的类型,例如void*,   能)。

这意味着void中的int bar(void);关键字确实引用了void类型。 由于typedef名称是命名类型的同义词,int bar(VOID);应该是同等合法的。对于像VOID这样的typedef名称来说,最有意义的是接受它void的{​​{1}},但标准的措辞实际上是指关键字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。我添加了一个过于冗长的注释,建议代码有效并且不应该生成错误消息 - 以及稍后的注释,承认代码无效,但是警告比致命错误更合适。

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

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