94

The below fails to compile:

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

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

but if I change it to

sizeof(arr);

everything is fine. Why?

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
blueshift
  • 6,742
  • 2
  • 39
  • 63
  • sizeof as an operator is not avaliable in ansi-c – Grim May 05 '11 at 08:44
  • 2
    @Kostya: my copy of K&R (the earliest description of the C language I have) is very far away and I can't check it now, but I'm 110% sure it describes `sizeof` fundamentally the same way C99 Standard does today. `sizeof` is available since before C was standardized by ANSI in 1989. – pmg May 05 '11 at 09:09
  • @Grim Your statement "sizeof as an operator is not available in ansi-c" is wrong. C90 has a section 3.3.3.4 "The sizeof operator". In C99, this moved to section 6.5.3.4. – Roland Illig Mar 27 '21 at 08:24

3 Answers3

136

According to 6.5.3, there are two forms for sizeof as the following:

sizeof unary-expression
sizeof ( type-name )

Since arr in your code is a type-name, it has to be parenthesized.

Ise Wisteria
  • 11,259
  • 2
  • 43
  • 26
  • 18
    +1 and, just to reinforce that `sizeof` is an operator: the parenthesis "belong to" the type, not the operator. – pmg May 05 '11 at 09:10
  • @pmg: Thanks for clarification! Yes, as you mentioned, the standard denotes `sizeof` as an operator. – Ise Wisteria May 05 '11 at 09:19
  • A7.4.8 in K&R, for retrogrouches like me. – jtniehof May 05 '11 at 14:04
  • 7
    @pmg: I don't think it's clear what the parentheses "belong to". The syntax of the second form consists of three tokens and one non-terminal: `sizeof ( type-name )`. But for the first form, you *can* write, for example, `sizeof(x)`, and though it looks like a function call (if `sizeof` weren't a keyword), it's really an operator applied to a parenthesized expression. Is that what you had in mind? – Keith Thompson Aug 09 '11 at 00:45
  • 3
    What I mean is that `sizeof` is, syntactically `sizeof ` as opposed to functions, for instance, to a `printf` which is `printf ( )`. The parenthesis belong to the `printf` but not to `sizeof`. When `sizeof` is applied to a parenthesized type name, I like to think of that as a cast of nothing -- "returning" just the type. – pmg Aug 09 '11 at 08:51
  • 3
    @pmg: You can certainly think of it that way, but I find it misleading. The only real resemblance to a cast is that it has a type name in parentheses, and that's just a coincidence of syntactic convenience. I prefer to think of `sizeof ( type-name )` as its own kind of expression. (The standard calls it an operator, but `( type-name )` isn't really an operand in the usual sense.) – Keith Thompson Aug 17 '11 at 16:16
  • Just for fun: `sizeof(0)["abcdefghij"]` is `1`. – melpomene Feb 18 '17 at 14:16
  • 1
    @melpomene A more common way to write `sizeof(0)["abcdefghij"]` is `sizeof("abcdefghij"[0])`. See http://stackoverflow.com/q/381542/ – jcsahnwaldt Reinstate Monica Mar 05 '17 at 11:27
56

That's the way the language is specified, type names must be parenthesized here.

Suppose the grammar looked like this:

sizeof unary-expression sizeof type-name

Now, e.g. the following expression would be ambiguous:

sizeof int * + 0

It could be either sizeof(int *) + 0 or sizeof(int) * +0. This ambiguity doesn't arise for unary expressions, as an asterisk appended to an expression isn't an expression (but for some type names, appending one, is again a type name).

Something had to be specified here and requiring type-names to be parenthesized is a way to solve the ambiguity.

mafso
  • 5,433
  • 2
  • 19
  • 40
-4

I think it's because you have typedef. If you remove it, it should compile.

Example from wikipedia:

/* 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));
clinton3141
  • 4,751
  • 3
  • 33
  • 46
baz
  • 1,317
  • 15
  • 10