Ian Collins <ia******@hotmail.comwrites:

li*****@hotmail.com wrote:
> I am puzzled on this C puzzle:

How to interpret this C statement: sizeof (int) * p

Is that the size of integer type multiplies p or the size of

whatever p points to in integer type?

I think it should be the latter because there are 4 parser tokens

here, sizeof, int, * and p, the first and the second are of same

precedence which are higher than the third and all three operators are

right associativity.

So I would parse the code into sizeof ((int) (* p))

But it does turn right. I have the following test code:

void main() {

It's probably upset at you for the above!

> int pp = 1;

int* p = &pp;

sizeof (int) * p;

}

I use GCC to compile it and get the following error:

main.c:4: invalid operands to binary *

So compiler takes "*" as multiplication.

Do you see at what point I am wrong?

You can't multiply by a pointer, p is an int*

Yes, but there is a valid question buried among a number of

unfortunate errors. Depending on how the expression is parsed, this:

sizeof (int) * p

could be either a multiplication whose left operand is a sizeof:

(sizeof (int)) * p /* legal if p is numeric */

or a sizeof whose right operand is a cast of a dereference:

sizeof ((int) * p) /* legal if p is a pointer to some numeric type */

This is similar to the question of whether a+b*c means (a+b)*c)

or a+(b*c). There is a single correct answer: it means a+(b*c),

because multiplication has higher precedence (binds more tightly)

than addition. Likewise, there's a single correct answer for

"sizeof ((int) (* p))".

The syntax for the sizeof operator is:

sizeof unary-expression

sizeof ( type-name )

The expression "sizeof (int) * p" cannot satisfy either of those.

It obviously can't match the second form, because the expression

doesn't end in a ')' character, but what about the first? Well,

"(int) * p" is an expression, but it's *not* a "unary-expression".

Why? Because the syntax for a unary-expression is:

unary-expression:

postfix-expression

++ unary-expression

-- unary-expression

unary-operator cast-expression

sizeof unary-expression

sizeof ( type-name )

unary-operator: one of

& * + - ~ !

In fact, "(int) * p" is a cast-expression:

cast-expression:

unary-expression

( type-name ) cast-expression

(All cast-expressions are unary-expressions, but not vice versa).

The other possibitility is that "sizeof (int) * p" is a

multiplicitive-expression. The syntax for that is:

multiplicative-expression:

cast-expression

multiplicative-expression * cast-expression

multiplicative-expression / cast-expression

multiplicative-expression % cast-expression

Our expression matches the second alternative here. The left operand,

"sizeof (int)", is a unary-expression, which is a cast-expression,

which is a multiplicative-expression. The right operand, "p", is an

identifier, which is a primary-expression, which [skipping a few steps]

is a cast-expression.

You can also make the same argument in terms of relative operator

precedences, but the standard doesn't use that concept.

--

Keith Thompson (The_Other_Keith)

ks***@mib.org <http://www.ghoti.net/~kst>

San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>

"We must do something. This is something. Therefore, we must do this."

-- Antony Jay and Jonathan Lynn, "Yes Minister"