考虑以下模糊的函数定义,返回指向char
s数组的指针:
char (*func(int var))[sizeof var]
{
return 0;
}
有效吗?
可疑部分是在var
表达式中使用标识符sizeof
。至少根据GCC 4.9.2,在var
表达式中看不到sizeof
。 (请注意,如果sizeof表达式中的var
替换为42
,则代码有效且此问题变得无趣。)
但是,在C11规范草案n1570中(相关部分在C99中相同,但可能有不同的子条款编号),第6.2.1节讨论了标识符的范围,并包含以下与此案例相关的句子:
6.2.1p4包含:
如果是声明符或类型说明符 声明标识符出现在块内或参数声明列表中 一个函数定义,标识符有块作用域,它终止于 相关区块。
6.2.1p7包含(bolding mine):
结构,联合和枚举标记的范围在外观之后开始 声明标记的类型说明符中的标记。每个枚举常量都具有该范围 在枚举器列表中出现其定义的枚举器之后开始。的不限 其他标识符的范围在其声明者完成之后开始。
显然,var
的声明符出现在函数定义中的参数声明列表中。因此,根据6.2.1p4,其范围在函数体的末尾结束("相关块")。此外,var
明确对应于"任何其他标识符"在6.2.1p7中提到,所以它的范围在其声明者完成之后,即在参数列表的末尾开始。
在我看来,规范没有说明var
的范围。鉴于规范并没有另外说明,对于"开头"的明显(对我来说,无论如何)解释。和"结束"范围意味着范围跨越从开始到结束的整个词汇间隔。因此,似乎var
实际上应该在sizeof
表达式中可见。
说明书中有什么东西我没有考虑到吗? 范围的标识符的概念是否应该以除了"从范围开头到范围结束的不间断词汇间隔的其他方式进行解释"?如果是这样,在规范中这是如何显现的?
答案 0 :(得分:2)
[sizeof var]
部分根本不是块的一部分,也不是声明列表的一部分,而是返回类型的一部分。因此,可见的唯一标识符是具有文件范围的标识符。
答案 1 :(得分:1)
函数的返回类型是在声明函数本身的块作用域或文件作用域中定义的。它不属于函数定义的最外部块范围。 在此范围内(声明函数),函数的参数尚未声明。
您可以将功能定义视为
return type: char ( * )[sizeof var] // Oops..What is var?!
{
// function block scope including its parameters declarations;
int var;
}