函数声明符中的参数声明是否具有函数原型范围?
C11 ISO标准(草案)第6.2.1(2)条将功能原型定义为(强调我的)
所以声明如void(* f)(struct s {int c;}); 标准的意图是说每个函数声明器中的参数列表定义了它自己的作用域(gcc和其他所有编译器似乎都解释了这个)?这个意图是否在标准的任何地方更正式地表达?任何尚未纳入标准的缺陷报告? 当然,这是一个语言律师问题,我很欣赏这种“偷偷摸摸”的标签声明是不好的风格.除了s在上面的声明中是不完整的类型之外,范围问题也使得用* f的原型定义函数变得不可能.最后,为了避免使用f本身的问题,可以将整个f的声明放在sizeof中,如int b [sizeof(void(*)(struct s {int c;}))]; 解决方法
在评论中进行长时间讨论的过程中,很明显这个问题实际上是关于§6.2.1/ 2中括号注释的确切含义,“函数原型是一个声明类型的函数的声明.它的参数.“
据我所知,“函数原型”这个短语没有正式的定义,它在标准中以各种方式使用.例如: >§6.2.7/ 3兼容型和复合型:
在这种情况下,“函数原型”的第一次使用显然不限于函数声明,因为它表示“函数类型” – 可能是在指向函数的指针的解析期间隐式创建的类型 – 并且“函数原型”的第二种用法可能根本没有语法表示,因为它是在复合类型算法过程中创建的类型 这里,第2段适用于具有“包含原型的类型”的函数,而第6段适用于具有“包含原型的类型”的函数的“不包括原型的类型”的函数.这些用法与上面“函数原型”的“定义”不兼容,因为该定义适用于整个函数类型,而“原型”的用法显然是在讨论函数类型的一部分. 本节标题可以解释为关于所有“函数声明符”,包括碰巧是“原型”的那些,或者是关于“函数声明符”和可能包含的“原型”.
这里的短语“函数原型”似乎是在谈论与函数类型相关或包含在函数类型中的东西,但函数声明符可以用作代理(“作为”). 我认为这不会超过像Principia Mathematica这样的作品的正式严格标准,但它与大多数法律规范和其他标准相同,其中需要一些常识来解释某些段落. 的确,有问题的引用:
意味着参数列表中的参数是类型声明而不仅仅是规范(如果两个短语之间确实存在差异). 另外,如果我们解构§6.2.1/ 4(下面部分引用),我们会看到它说:
然后继续列出“声明标识符的声明符或类型说明符”的三个备选项: >“出现在任何块或参数列表之外” 假设这三种可能性是排他性的(因此规定不是有序的)和全面的(因为它们必须适用于“每个标识符”).然后,常识必须引导我们假设函数原型是一个函数声明器,它包含一个参数列表,或者(在某些上下文中)来自该语法结构的一些子集或语义抽象,所以你的第一个问题的答案是“是”,这是标准的意图“. 这是否是标准中的缺陷是一个我不选择参与的意见问题.我检查了我认为是最新的清单](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2244.htm)并没有看到任何相关内容,因此据我所知它没有被报告为缺陷. 我的原始答案的某些版本如下,以防人们阅读评论. 标准对参数列表中标识符的范围所说的内容对我来说非常清楚. §6.2.1/ 4定义了参数列表中声明的标识符的两个可能范围(强调添加):
在问题的例子中,struct的声明符出现一个参数列表,它恰好是“参数声明列表”.所以第二句适用,它们的范围仅限于参数列表本身.这使得struct无效,因此编译器会警告你. 如果结构类型说明符出现在定义的参数列表中,则它可以在函数体内使用,但是该结构的任何实例都不能从定义出现的转换单元传递给该函数. 我相信标准的意图是标记类型的类型说明符声明出现在参数列表之外. §6.7.2.3(标签)的语言加强了这一点:
和
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |