Abi*_*ran 12 c typedef c99 c11
从C99标准来看,6.7(5):
声明指定一组标识符的解释和属性.标识符的定义是该标识符的声明:对于对象,导致为该对象保留存储; 对于一个功能,包括功能体; 对于枚举常量或typedef名称,是标识符的(唯一)声明.
如果标识符typedef实际上是定义,那么为什么允许它们被多次声明?例:
int main()
{
typedef int x;
typedef int x;
}
Run Code Online (Sandbox Code Playgroud)
上面的程序编译没有错误.这怎么可能?我期待该程序给我一个多重定义错误.
Jon*_*ler 14
规则在C99和C11之间变化(并且C11规则与C++规则匹配,据我所知).请注意,在这两个标准中,3在Constraints部分中,5在Semantics部分中.这对于错误消息很重要 - 约束违规需要诊断.
ISO/IEC 9899:1999§6.7声明
3如果标识符没有链接,则除了6.7.2.3中规定的标记之外,标识符(在声明符或类型说明符中)的声明不应超过一个具有相同作用域和相同名称空间的声明.
5声明指定一组标识符的解释和属性.标识符的定义是该标识符的声明:
- 对于一个对象,导致为该对象保留存储;
- 对于一个函数,包括函数体; 98)
- 对于枚举常量或typedef名称,是标识符的(唯一)声明.
ISO/IEC 9899:2011§6.7声明
3如果标识符没有链接,则标识符的声明(在声明符或类型说明符中)不得超过一个具有相同作用域和相同名称空间的声明,但以下情况除外:
- 如果类型不是可变修改类型,则可以重新定义typedef名称以表示与其当前相同的类型;
- 标签可以按照6.7.2.3中的规定重新声明.
5声明指定一组标识符的解释和属性.标识符的定义是该标识符的声明:
- 对于一个对象,导致为该对象保留存储;
- 对于一个函数,包括函数体; 119)
- 对于枚举常量,是标识符的(唯一)声明;
- 对于typedef名称,是标识符的第一个(或唯一的)声明.
Lundin 指出,标准C委员会的网站包含n1360,这是一份单页文件,详细说明了为何进行此项更改.基本上:C++就是这样做的; 一些编译器已经做到了; 既不难做也不颠覆任何东西以允许(要求)它.
如果您的代码正在编译,那么它将根据C11规则或C++规则进行编译.它不是根据(严格)C99规则编译的.
请注意,除非您另有说明,否则GCC的最新版本允许重新定义,但也请注意John Bollinger的报告,即GCC 4.4.7(在未识别的平台上)不允许在C99模式下重新定义.
考虑一下文件retypedef.c:
int main(void)
{
typedef int x;
typedef int x;
x y = 0;
return y;
}
Run Code Online (Sandbox Code Playgroud)
使用GCC 4.9.1在Mac OS X 10.9.5上进行编译,得到:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -c retypedef.c
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -pedantic -c retypedef.c
$ gcc -O3 -g -std=c99 -Wall -Wextra -Werror -c retypedef.c
$ gcc -O3 -g -std=c99 -Wall -Wextra -Werror -pedantic -c retypedef.c
retypedef.c: In function ‘main’:
retypedef.c:4:17: error: redefinition of typedef ‘x’ [-Werror=pedantic]
typedef int x;
^
retypedef.c:3:17: note: previous declaration of ‘x’ was here
typedef int x;
^
cc1: all warnings being treated as errors
$
Run Code Online (Sandbox Code Playgroud)
除非-pedantic使用,否则它不会抱怨,只有在请求C99时才符合要求(符合标准,typedef在C11中重新定义相同的范围).