sizeof an integer expression in C
Asked Answered
E

3

7

To my semi-surprise with Xcode compiling C (gnu11)

#include <stdio.h>
int main(int argc,char**argv)
{
    short s = 1;
    printf( "%zd %zd %zd\n", sizeof(s), sizeof(s*s), sizeof(s?s:s));
    return 0;
}

Produces the output

2 4 4

I was expecting

2 2 2

or possibly

2 4 2

Why is this?

Eiser answered 11/10, 2015 at 19:7 Comment(0)
E
8

I recalled from K&R that any integer expression smaller than an int is promoted to int. I found this in Standard (C89):

3.2.1.1 Characters and integers

A char, a short int, or an int bit-field, or their signed or unsigned varieties, or an object that has enumeration type, may be used in an expression wherever an int or unsigned int may be used. If an int can represent all values of the original type, the value is converted to an int;

The surprise is s?s:s because all reference I could find say the resulting type is an lvalue but that's just C++. C treats it as an rvalue. As expected then, C++'s output is:

2 4 2

Even if the expression is an rvalue. An unexpected difference between C and C++.

Eiser answered 11/10, 2015 at 19:7 Comment(1)
Another subtle difference between C and C++ visible with the sizeof operator is this: printf("%zd\n", sizeof('s')); may print 4 in C but always 1 in C++.Direction
N
6

This is because the latter two sizeof operands contain operators. In C, types narrower than int are promoted to int before the operation is performed. So s * s is an int multiplied with an int, yielding an int.

Similarly for short ? short : short getting promoted to int ? int : int.

Noe answered 11/10, 2015 at 19:23 Comment(1)
In the spec I found, it's called a conditional expression and not called a ternary operator. The ',' operator doesn't promote, even for bit fields and works as I'd expect :? to. It seems it's one of those things you just have to know.Eiser
K
4

According to C11§6.5.15/5:

If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result. [...]

In your case, the result is equal to sizeof(int) because the 'usual arithmetic conversions' promote the shorts to ints. Same as with sizeof(s*s).

Kore answered 11/10, 2015 at 19:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.