C ++ / CLI:将“VOID”解释为“void”

时间:2014-07-04 14:09:37

标签: c++-cli

我正在做一些非常丑陋的事情,但是似乎有些东西似乎是一个错误..

我有enum名为BasicTypeID,用 C#编写:

public enum BasicTypeID
{
    //..
    FUNCTION,
    VOID,
    FLOAT,
    // ..
}

当我尝试为位置BasicTypeID :: VOID上的数组元素赋值时,如下所示:

typedef struct TypeInfo {
    char * name;
    unsigned char size;
    unsigned char sign;
    unsigned char real;
} TypeInfo;

static const TypeInfo TYPE_VOID = { "void", 0, 0, 0 };

static TypeInfo const **basic_type_info;

CDLLEXPORT void CLIParser_InitializeDebugInformation(char * source_folder_path, char * cdb_file_path) 
{
  // ..

  int enum_size = Enum::GetNames(BasicTypeID::typeid)->Length;

  *basic_type_info = new TypeInfo[enum_size];

  basic_type_info[(int)BasicTypeID::VOID] = &TYPE_VOID; // Compile error

  VOID *dummy1;
  FLOAT dummy2;

  // ..
}

我收到了错误:

error C2589: 'void' : illegal token on right side of '::'
error C2059: syntax error : '::'

如果我使用例如它是有效的FUNCTION作为索引:

basic_type_info[(int)BasicTypeID::FUNCTION] = &TYPE_VOID; // Compiles without errors

它也适用于FLOAT

basic_type_info[(int)BasicTypeID::FLOAT] = &TYPE_VOID; // Compiles without errors

为什么会这样?

1 个答案:

答案 0 :(得分:2)

Windows标头有#define VOID void,这会混淆您的C ++ / CLI代码。

他们为什么这样做?因为在第一次定义Windows API的那天,对void的C编译器支持并不统一。由于API必须与这些编译器一起使用,因此它在VOID中提供了自己的版本,如果您的编译器支持它,可能会扩展为void,如果不支持,则推广到其他类型。然后,由于向后兼容性,他们无法做任何事情。

为什么不是typedef?因为当时的微软编译器显然不认为typedef void VOID;是合法的C(他们现在这样做,我相信)。并且他们必须保留宏以实现向后兼容,因为

#define VOID void
int c(VOID){ return 0; }

是合法的,

typedef void VOID;
int c(VOID){ return 0; }

不是(无论如何都是C89)。

几乎所有其他Windows API类型都是typedef而不是预处理器宏,这就是为什么FLOAT适合您但VOID没有。