[英]Are synonymous `typedef`s in C interchangable?
声明qboolean SNDDMA_InitDirect (void);
出现在第69行的'WinQuake / snd_win.c'中 。 但是, 函数的定义(出现在同一文件的第183行写为:
sndinitstat SNDDMA_InitDirect (void)
{
/* Actual implementation is unimportant in this discussion. */
}
qboolean
和sndinitstat
都是枚举的typedef
: sndinitstat
在'WinQuake / snd_win.c'的第33行 ,
typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
和qboolean
在'WinQuake / COMMON.H'(第30行)
typedef enum {false, true} qboolean;
这些是不同的枚举 。
我一直在使用Visual Studio 2015的内置编译器( cl.exe )和Clang v3.7.1通过Visual Studio的LLVM插件编译此源代码。 Clang说声明/定义的这种差异是错误的。 Visual Studio编译好了。 谁是对的?
现在,引用C:A参考手册(第四版) :
第5.5节枚举类型 (第127页)
枚举常量在定义类型时指定,其类型为
int
。
第5.10节“ Typedef名称” (第149页)
使用
typedef
存储说明符的声明不会引入新类型; 对于可以通过其他方式指定的类型,名称被视为同义词。
这两段对我来说就好像Clang的错误虽然有用但根据标准不正确。 但我知道微软在正确编译C方面没有最大的声誉。
它们引用了不同的枚举:
typedef enum {false, true} qboolean;
typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
根据6.2.5:16,
每个不同的枚举构成不同的枚举类型。
所以Clang肯定是正确的。
如果隐藏在typedef名称后面的枚举类型qboolean
和sndinitstat
是兼容的 ,那么代码就可以了。 如果它们不兼容 ,则代码是错误的。 (参见6.2.7兼容型和复合型 )。
如果两个函数声明都存在于同一个转换单元中,那么返回类型兼容性要求对于类型必须相同的点变得更加严格。
在您的情况下,两个无标记枚举类型用于定义这些typedef
名称。 枚举声明完全不同,使它们不兼容 。 这意味着有问题的代码确实包含错误,Clang是抱怨的权利。 Visual Studio错过了此错误。
请注意,虽然Clang(以及GCC)将它带到另一个极端 - 即使没有,它们也会报告错误。
例如,这些声明
enum { A1, A2, A3 } foo(); enum { B1, B2, B3 } foo();
即使代码有效,在Clang和GCC中也会导致相同的错误。
在此示例中,无标记枚举类型是
兼容的 ,这足以证明声明之间
foo
的返回类型的更改是合理的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.