tags:

views:

604

answers:

10

It seems sizeof is not a real function?

for example, if you write like this:

int i=0;
printf("%d\n", sizeof(++i));
printf("%d\n", i);

You may get output like:

4
0

And when you dig into the assemble code, you'll find sth like this:

movl     $4, %esi
leaq     LC0(%rip), %rdi
xorl %eax, %eax
call     _printf

So, the compiler put directly the constant "4" as parameters of printf add call it. Then what does sizeof do?

+7  A: 

Sizeof analyzes the passed expression to find its type. It then returns the size of the type.

Because the size of a type is always known at compile time, it is put into the machine code as a constant.

Timbo
+1 in C++, and pre C99. In C99, the size of a type is not always known at compile time: `void f( int N ) { int array[N]; printf( "%d\n", sizeof(array) ); }`. In this case, the size of the array is not known at compile time but at runtime.
David Rodríguez - dribeas
A: 

Exactly what it's meant to do: puts directly the constant "the size of the variable/constant/type/etc" into the code

valya
+2  A: 

It is replaced with the constant (4 in your case) at compile time. Because it takes 4 bytes to hold an int on your platform.

And your code will not compile, instead of giving you any output ;-) Because of sizoef ;-)

Michael Krelin - hacker
thanks for the notice. I've corrected the typo. ;)
ibread
you're welcome ;-)
Michael Krelin - hacker
BTW, it depends on the implementation, but I doubt most of them will produce call to `_printf` when doing `operator<<` for cout.
Michael Krelin - hacker
+1  A: 

The size of returned type is calculated at compile time, there is no runtime overhead

Chris Bednarski
A: 

sizeof() returns the size in bytes of whatever you pass as an argument to it. In a 32-bit architecture sizeof(int) would return 4, while sizeof(char) would return 1.

arclight
+28  A: 

You know, there's a reason why there are standard documents (3.8MB PDF); C99, section 6.5.3.4, §2:

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.


In response to ibread's comment, here's an example for the C99 variable length array case:

#include <stdio.h>

size_t sizeof_int_vla(size_t count)
{
    int foo[count];
    return sizeof foo;
}

int main(void)
{
    printf("%u", (unsigned)sizeof_int_vla(3));
}

The size of foo is no longer known at compile-time and has to be determined at run-time. The generated assembly looks quite weird, so don't ask me about implementation details...

Christoph
There's also a reason why stackoverflow.com exists.
jalf
+1 for digging up the excerpt
Paul Dixon
@jalf: "Teach a man to fish and you feed him for a lifetime. Unless he doesn't like sushi—then you also have to teach him to cook." - or something ;)
Christoph
So, is there an example to show that "variable length array type" case?
ibread
Perhaps not immediately obvious from the above snippet, any function call or side effect in a sizeof that takes the size of a VMT (variably modified type), as is the type of a VLA, causes the side effect to happen if it's important for determining the value: `int gimme(void) { format("C:/"); return 2; } int main(void) { sizeof(int[gimme()]); }`. This will actually format :) Conversely, whether the following will format is unspecified: `sizeof((int(*)[format()])0)`: changing the value of `format()` will not change the result of sizeof (for impls where all object pointers have the same size).
Johannes Schaub - litb
+1  A: 

In C++ sizeof() calculates size of the type of the expression within it and replaces the whole "sizeof() function call" with a constant during compilation.

The expression within sizeof() is never evaluated during the program execution. And it may not even be a type name. Check these examples out:

struct X { int i; double j;};
int call_to_undefined_function();

sizeof(10/0);
sizeof( ((struct X*)NULL)->j );
sizeof( call_to_undefined_function() + 100 );
sizeof( call_to_undefined_function() + 100.0 );
sizeof( double() / int() );
Pavel Shved
A: 

what i'd like to figure out is that the following code doesn't work w/ GNU C/++:

#if sizeof(long) < 8
printf("not a 64 bits platform\n";
#else
printf("a big system\n");
#endif

I thought the code works because sizeof() is a compile-time facility and sizeof(long) is a constant.

who can explain?

EffoStaff Effo
the preprocessor (translation phase 4) doesn't know about C semantics (translation phase 7) - it'll only see the preprocessor token `sizeof`, but doesn't know that it should interpret it as an operator returning a compile-time constant
Christoph
good answer, though doesn't make sense to me. all compilers work that way or just one or two?
EffoStaff Effo
@EffoStaff Effo: it's in the C standard, so any conforming implementations has to do it like this; the reason is that preprocessor and compiler initially were (and normally still can be used as) independant programs
Christoph
+11  A: 

sizeof is an operator, not a function.

It's usually evaluated as compile time - the exception being when it's used on C99-style variable length arrays.

Your example is evaluating sizeof(int), which is of course known at compile time, so the code is replaced with a constant and therefore the ++ doesn't exist at run-time to be executed.

int i=0;
cout << sizeof(++i) << endl;
cout << i << endl;

It's also worth noting that since it's an operator, it can be used without the brackets on values:

int myVal;
cout << sizeof myVal << endl;
cout << sizeof(myVal) << endl;

Are equivalent.

therefromhere
there's a small error: `sizeof int` is not valid C as types have to be parenthesised!
Christoph
ah, sorry, fixed.
therefromhere
+1 for correctly saying it's an operator, not a function
sbi
A: 

You said it yourself: 'sizeof' is not a function. It is a built-in operator with special syntax and semantics (see the previous responses). To remember better that it is not a function, you might want to get rid of the habit to use superfluous braces and prefer to use the "braceless" 'sizeof' with expressions as in the following example

printf("%d\n", sizeof ++i);

This is exactly equivalent to your original version.

AndreyT