C中的同义词`typedef`是可互换的吗?

时间:2016-02-05 23:20:03

标签: c visual-studio clang typedef

声明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. */
}

qbooleansndinitstat {}为枚举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方面没有最大的声誉。

2 个答案:

答案 0 :(得分:3)

他们引用不同的枚举:

typedef enum {false, true}  qboolean;
typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;

根据6.2.5:16,

  

每个不同的枚举构成不同的枚举类型。

所以Clang肯定是正确的。

答案 1 :(得分:1)

如果隐藏在typedef名称qbooleansndinitstat后面的枚举类型兼容,那么代码就可以了。如果它们不兼容,则代码是错误的。 (见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的返回类型的更改。