【发布时间】:2015-03-05 20:20:51
【问题描述】:
考虑以下函数的模糊定义,该函数返回指向chars 数组的指针:
char (*func(int var))[sizeof var]
{
return 0;
}
有效吗?
有问题的部分是sizeof 表达式中标识符var 的使用。至少根据 GCC 4.9.2,var 在 sizeof 表达式中不可见。 (请注意,如果将 sizeof 表达式中的 var 替换为 42,则代码是有效的,这个问题就变得无趣了。)
然而,在 C11 规范草案 n1570 中(相关部分在 C99 中相同,尽管可能有不同的子条款编号),子条款 6.2.1 讨论了标识符的范围,并包含以下与此情况相关的句子:
6.2.1p4 包含:
如果声明符或类型说明符 声明标识符出现在块内或参数声明列表中 一个函数定义,标识符有块作用域,它终止于 关联块。
6.2.1p7 包含(加粗我的):
结构、联合和枚举标记的范围紧随其出现之后开始 声明标签的类型说明符中的标签。每个枚举常量的范围 在其定义的枚举数出现在枚举数列表中之后开始。 任何 其他标识符的范围在其声明符完成后开始。
显然,var 的声明符出现在函数定义的参数声明列表中。因此,根据 6.2.1p4,其范围在函数体(“关联块”)的末尾结束。此外,var 明显对应于 6.2.1p7 中提到的“任何其他标识符”,因此它的范围在其声明符完成后开始,即在参数列表的末尾。
在我看来,规范中没有提到与var 的范围相关的其他内容。鉴于规范没有另外说明,对范围的“开始”和“结束”的明显(对我来说,无论如何)解释意味着范围跨越从开始到结束的整个词汇区间。因此,var 似乎实际上应该在 sizeof 表达式中可见。
规范中有没有我没有说明的地方? 标识符的作用域的概念是否意味着以某种其他方式解释,而不是“从作用域开始到作用域结束的不间断词法区间”?如果是这样,这在规范中是如何体现的?
【问题讨论】:
-
仅供参考,gcc 并不孤单。带有 -std=C11 的 clang 3.5 报告相同的错误(未声明的标识符:
var)。
标签: c function parameters scope language-lawyer