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

时间:2015-05-31 12:58:55

标签: c arrays language-lawyer sizeof parentheses

以下程序在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)。

2 个答案:

答案 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节结构所暗示的分类)。