【发布时间】:2018-10-26 12:36:10
【问题描述】:
C11 ISO 标准(草案)的第 6.2.1(2) 条将函数原型定义为(强调我的)
函数原型是函数的声明,它声明了其参数的类型。
所以声明如void (*f)( struct s { int c; } );
不是函数的声明(它是指向函数的指针的声明),因此标记 s 具有文件或块范围(取决于此声明出现的位置)。然后似乎以下翻译单元void (*f)( struct s { int c; } ); struct s a[42];
应该完全符合(撇开任何可用性问题)。然而,gcc 会产生一个诊断性的“不完整类型数组”(以及关于s 的范围仅限于参数列表的警告),表明s 具有函数原型范围,即使正式没有函数声明。
标准的意图是说每个函数 declarator 中的参数列表定义了自己的范围(gcc 和所有其他编译器似乎都是这样解释的)?这种意图是否在标准的任何地方更正式地表达?任何尚未纳入标准的缺陷报告?
当然,这是一个语言律师的问题,我很欣赏这种“偷偷摸摸”的标签声明是不好的风格。除了s 是上述a 声明中的不完整类型之外,范围问题也使得无法定义 具有*f 原型的函数。最后,为了避免使用f 本身的问题,可以将f 的整个声明放在sizeof 中,如int b[sizeof(void (*)( struct s { int c; } ))];
【问题讨论】:
-
“
warning: its scope is only this definition or declaration, which is probably not what you want”有什么难理解的?您的原型同时声明了 参数类型 和 类型定义 本身 - 语法上有效,但实际上无用.. -
@Clifford:检查 [language-lawyer] 标签。警告不难理解,但对吗?如果是这样,为什么?为什么范围这么小?
-
@Clifford:有点吹毛求疵,
struct并非完全无用,因为人们可以用适当的原型定义一个函数,甚至在 不同的翻译单元,根据 6.2.7(1),尽管这种做法值得怀疑。问题是gcc是否遵循标准,而不是为什么它会抛出这个警告。 -
@MSalters :我很欣赏这个标签,这就是为什么我发表评论而不是答案。我的意思很简单,问题是“标签 s 具有文件或块范围”,而显然它具有 声明范围。可能是 stackoverflow.com/questions/16831605/… 的近似副本
-
@Clifford:绝对相关,但这不是 [语言律师] 的问题。此处的正确答案将显示 C11 的哪个部分使标记
s具有 声明范围(“会”,因为 alexsh 是正确的。C11 有 4 种类型的范围,并且 声明范围 不是其中之一)
标签: c scope language-lawyer c11