Почему (и когда) мне нужно использовать круглые скобки после sizeof?

Ниже не удается скомпилировать:

typedef int arr[10];
int main(void) {
    return sizeof arr;
}

sizeof.c:3: error: expected expression before ‘arr’

но если я изменю его на

sizeof(arr);

все в порядке. Почему?

Ответ 1

В соответствии с 6.5.3 для sizeof существуют две формы:

sizeof unary-expression
sizeof ( type-name )

Так как arr в вашем коде есть type-name, он должен быть заключен в скобки.

Ответ 2

Чтобы указать язык, имена типов должны быть заключены в круглые скобки.

Предположим, что грамматика выглядела так:

sizeof unary-expression sizeof type-name

Теперь, например. следующее выражение будет неоднозначным:

sizeof int * + 0

Это может быть либо sizeof(int *) + 0, либо sizeof(int) * +0. Эта неоднозначность не возникает для унарных выражений, поскольку звездочка, добавленная к выражению, не является выражением (но для некоторых имен типов, добавляя один, это опять-таки имя типа).

Что-то должно было быть указано здесь, и требуя, чтобы имена типов были заключены в круглые скобки, это способ решить двусмысленность.

Ответ 3

Я думаю, потому что у вас есть typedef. Если вы удалите его, он должен скомпилироваться.

Пример из википедии:

/* the following code fragment illustrates the use of sizeof     
 * with variables and expressions (no parentheses needed),
 * and with type names (parentheses needed)    
 */
char c;
printf("%zu,%zu\n", sizeof c, sizeof (int));