C中的同义`typedefs可以互换吗?
Are synonymous `typedef`s in C interchangable?
出现在'WinQuake/snd_win.c' on line 69. However, the function's definition (appearing on line 183 of the same file中的声明qboolean SNDDMA_InitDirect (void);
写成:
sndinitstat SNDDMA_InitDirect (void)
{
/* Actual implementation is unimportant in this discussion. */
}
qboolean
和sndinitstat
都是枚举的typedef
:sndinitstat
on line 33 of 'WinQuake/snd_win.c',
typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
和 qboolean
在 'WinQuake/common.h' (line 30)
typedef enum {false, true} qboolean;
这些是不同的枚举。
我一直在使用 Visual Studio 2015 的内置编译器——cl.exe——和 Clang v3.7.1 通过 LLVM 插件编译这个源代码Visual Studio。 Clang 声明 declaration/definition 中的这种差异是一个错误。 Visual Studio 可以编译。 谁是正确的?
现引用C:参考手册(第四版):
第 5.5 枚举类型(第 127 页)
The enumeration constants are specified when the type is defined and have the type int
.
第 5.10 Typedef 名称(第 149 页)
Declarations with the typedef
storage specifier do not introduce new types; the names are considered synonymous for types that could be specified in other ways.
这两段读起来好像 Clang 的错误虽然有帮助,但根据标准是不正确的。但我知道微软在正确编译 C 方面并没有最大的声誉。
它们指的是不同的枚举:
typedef enum {false, true} qboolean;
typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
根据 6.2.5:16,
Each distinct enumeration constitutes a different enumerated type.
所以 Clang 肯定是正确的。
如果隐藏在 typedef 名称 qboolean
和 sndinitstat
后面的枚举类型是 compatible,那么代码是可以的。如果它们不兼容,则代码是错误的。 (参见 6.2.7 Compatible type and composite type)。
如果两个函数声明出现在同一个翻译单元中,那么 return 类型兼容性要求变得更加严格,以至于类型必须 相同 .
在您的例子中,两个无标记枚举类型用于定义这些 typedef
名称。枚举声明完全不同,使它们不兼容。这意味着有问题的代码确实包含错误,而 Clang 的抱怨是正确的。 Visual Studio 漏掉了这个错误。
请注意,尽管 Clang(以及 GCC)将它带到了另一个极端 - 即使存在 none,它们也会报告错误。例如,这些声明
enum { A1, A2, A3 } foo();
enum { B1, B2, B3 } foo();
即使代码有效,也会在 Clang 和 GCC 中导致相同的错误。在此示例中,无标记枚举类型是 compatible,这足以证明声明之间 return 类型 foo
的更改是合理的。
出现在'WinQuake/snd_win.c' on line 69. However, the function's definition (appearing on line 183 of the same file中的声明qboolean SNDDMA_InitDirect (void);
写成:
sndinitstat SNDDMA_InitDirect (void)
{
/* Actual implementation is unimportant in this discussion. */
}
qboolean
和sndinitstat
都是枚举的typedef
:sndinitstat
on line 33 of 'WinQuake/snd_win.c',
typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
和 qboolean
在 'WinQuake/common.h' (line 30)
typedef enum {false, true} qboolean;
这些是不同的枚举。
我一直在使用 Visual Studio 2015 的内置编译器——cl.exe——和 Clang v3.7.1 通过 LLVM 插件编译这个源代码Visual Studio。 Clang 声明 declaration/definition 中的这种差异是一个错误。 Visual Studio 可以编译。 谁是正确的?
现引用C:参考手册(第四版):
第 5.5 枚举类型(第 127 页)
The enumeration constants are specified when the type is defined and have the type
int
.第 5.10 Typedef 名称(第 149 页)
Declarations with the
typedef
storage specifier do not introduce new types; the names are considered synonymous for types that could be specified in other ways.
这两段读起来好像 Clang 的错误虽然有帮助,但根据标准是不正确的。但我知道微软在正确编译 C 方面并没有最大的声誉。
它们指的是不同的枚举:
typedef enum {false, true} qboolean;
typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
根据 6.2.5:16,
Each distinct enumeration constitutes a different enumerated type.
所以 Clang 肯定是正确的。
如果隐藏在 typedef 名称 qboolean
和 sndinitstat
后面的枚举类型是 compatible,那么代码是可以的。如果它们不兼容,则代码是错误的。 (参见 6.2.7 Compatible type and composite type)。
如果两个函数声明出现在同一个翻译单元中,那么 return 类型兼容性要求变得更加严格,以至于类型必须 相同 .
在您的例子中,两个无标记枚举类型用于定义这些 typedef
名称。枚举声明完全不同,使它们不兼容。这意味着有问题的代码确实包含错误,而 Clang 的抱怨是正确的。 Visual Studio 漏掉了这个错误。
请注意,尽管 Clang(以及 GCC)将它带到了另一个极端 - 即使存在 none,它们也会报告错误。例如,这些声明
enum { A1, A2, A3 } foo();
enum { B1, B2, B3 } foo();
即使代码有效,也会在 Clang 和 GCC 中导致相同的错误。在此示例中,无标记枚举类型是 compatible,这足以证明声明之间 return 类型 foo
的更改是合理的。