在确定数组的大小时,括号会有所作为吗?

fre*_*low 26 c arrays sizeof parentheses language-lawyer

以下程序在gcc 4.8.2上两次打印相同的数字:

#include <stdio.h>

int main()
{
    char a[13];
    printf("sizeof a  is %zu\n", sizeof a );
    printf("sizeof(a) is %zu\n", sizeof(a));
}
Run Code Online (Sandbox Code Playgroud)

根据这篇reddit帖子,gcc在这方面并不符合标准,因为当数组到指针衰减没有发生时,括号表达式不在异常列表中.

这家伙是对的吗?这是相关的标准报价:

除非它是运算sizeof符或一元运算&符的操作数,或者是用于初始化字符数组数组的字符串文字,或者是用于初始化与元素类型兼容的数组的宽字符串文字,否则具有wchar_t的左值类型'array of type'被转换为一个表达式,其类型为'指向类型的指针',指向数组对象的初始成员而不是左值.

为了清楚起见,他认为(a)应该触发数组到指针的衰减,因为上面的列表中没有括号括起来(sizeof运算符,一元运算&符,字符串文字作为初始值).

小智 26

看似冗余的括号是否会影响程序的语义是C标准中一个长期存在的问题,但仍未得到充分解决.

通常声称((void*)0)技术上不是空指针常量,因为没有规则表明带括号的空指针常量是空指针常量.

某些编译器会发出错误char s[] = ("abc");,因为虽然可以从字符串文字初始化字符数组,但该规则不会涵盖带括号的字符串文字.

有许多类似的例子.你找到了其中一个.

据我所知,共识基本上是规则应该是C++所做的,但C从未正式采用.C++使得带括号的表达式在功能上等同于非带括号的表达式,并带有一些明确说明的异常.这将同时涵盖所有这些问题.

从技术上讲,这个人可能被认为是正确的,但这是对标准的过于严格的解释,没有人真正遵循,因为众所周知,标准在这里是错误的.


Oli*_*rth 21

从C99,6.5.1开始,在带括号的表达式上:

它的类型和值与未表示的表达式相同.

乍一看,这似乎与您所指的例外列表冲突(6.3.2.1):

除非它是运算sizeof符或一元运算&符的操作数,或者是用于初始化数组的字符串文字,否则将类型为"数组类型"的表达式转换为类型为"指向类型的指针"的表达式...

但是,此列表位于运算符/操作数的上下文中; 括号似乎不被视为运营商(基于6.5节结构所暗示的分类).