声明qboolean SNDDMA_InitDirect (void);
出现在'WinQuake/snd_win.c' on line 69中。但是,function's definition (appearing on line 183 of the same file写为:
sndinitstat SNDDMA_InitDirect (void)
{
/* Actual implementation is unimportant in this discussion. */
}
qboolean
和sndinitstat
{}为枚举typedef
line 33 of 'WinQuake/snd_win.c',
sndinitstat
在'WinQuake/common.h' (line 30) 中和typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
qboolean
这些是不同的枚举。
我一直在使用Visual Studio 2015的内置编译器 - cl.exe - 和Clang v3.7.1通过Visual Studio的LLVM插件编译此源代码。 Clang说声明/定义的这种差异是错误的。 Visual Studio编译好了。 谁是对的?
现在,引用 C:A参考手册(第四版):
部分 5.5枚举类型(第127页)
在定义类型并且类型为
typedef enum {false, true} qboolean;
时指定枚举常量。
部分 5.10 Typedef名称(第149页)
使用
int
存储说明符的声明不会引入新类型;这些名称被认为是可以通过其他方式指定的类型的同义词。
这两段在我看来,好像Clang的错误虽然有用但根据标准不正确。但我知道微软在正确编译C方面没有最大的声誉。
答案 0 :(得分:3)
他们引用不同的枚举:
typedef enum {false, true} qboolean;
typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
根据6.2.5:16,
每个不同的枚举构成不同的枚举类型。
所以Clang肯定是正确的。
答案 1 :(得分:1)
如果隐藏在typedef名称qboolean
和sndinitstat
后面的枚举类型兼容,那么代码就可以了。如果它们不兼容,则代码是错误的。 (见6.2.7 Compatible type and composite type)。
如果两个函数声明都存在于同一个翻译单元中,则返回类型兼容性要求变得更加严格,以至于类型必须相同。
在您的情况下,使用两个无标记枚举类型来定义这些typedef
名称。枚举声明完全不同,使它们不兼容。这意味着有问题的代码确实包含错误,Clang是抱怨的权利。 Visual Studio错过了这个错误。
注意虽然Clang(以及GCC)把它带到另一个极端 - 即使没有,它们也会报告错误。例如,这些声明
enum { A1, A2, A3 } foo();
enum { B1, B2, B3 } foo();
在Clang和GCC中导致相同的错误,即使代码有效。在此示例中,无标记枚举类型 compatible ,这足以证明声明之间 foo
的返回类型的更改。