以下程序在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));
}
根据this reddit post,gcc在这方面不符合标准,因为当数组到指针衰减没有发生时,带括号的表达式不在异常列表中。
这家伙是对的吗?以下是相关的标准报价:
除非它是
sizeof
运算符或一元&
运算符的操作数,或者是用于初始化字符数组数组的字符串文字,或者是用于以下的宽字符串文字初始化一个元素类型与wchar_t
兼容的数组,一个类型为'array of type'的左值被转换为一个表达式,其类型为'指向类型的指针',指向数组对象的初始成员而不是左值。
为了清楚起见,他认为(a)
应触发数组到指针的衰减,因为括号不在上面的列表中(sizeof
运算符,一元&
运算符, string literal as initializer)。
答案 0 :(得分:25)
看似多余的括号是否会影响程序的语义是C标准中一个长期存在的问题,但尚未得到充分解决。
通常声称((void*)0)
在技术上不是空指针常量,因为没有规则说明带括号的空指针常量是空指针常量。
有些编译器会为char s[] = ("abc");
发出错误,因为虽然可以从字符串文字初始化字符数组,但该规则不会涵盖带括号的字符串文字。
有很多类似的例子。你找到了其中一个。
据我所知,共识基本上是规则应该是C ++的功能,但C从未正式采用过。 C ++使得带括号的表达式在功能上等同于非带括号的表达式,并带有一些明确说明的异常。这将同时涵盖所有这些问题。
从技术上讲,这个人可能被认为是正确的,但这是对标准的过于严格的解释,没有人真正遵循,因为众所周知,标准在这里是错误的。
答案 1 :(得分:21)
来自C99,6.5.1,带括号的表达式:
它的类型和值与未表示的表达式相同。
乍一看,这似乎与您所指的例外列表冲突(6.3.2.1):
除非它是
sizeof
运算符或一元&
运算符的操作数,或者是用于初始化数组的字符串文字,否则将转换类型为“array of array”的表达式到类型为“指向类型的指针”的表达式...
但是,此列表位于运算符/操作数的上下文中;括号似乎不被视为运营商(基于6.5节结构所暗示的分类)。