Here is the code compiled in dev c++ windows:
#include
int main() {
int x = 5;
printf(\"%d and \", sizeof(x++)); // note 1
print
sizeof
is a compile-time operator, so at the time of compilation sizeof
and its operand get replaced by the result value. The operand is not evaluated (except when it is a variable length array) at all; only the type of the result matters.
short func(short x) { // this function never gets called !!
printf("%d", x); // this print never happens
return x;
}
int main() {
printf("%d", sizeof(func(3))); // all that matters to sizeof is the
// return type of the function.
return 0;
}
Output:
2
as short
occupies 2 bytes on my machine.
Changing the return type of the function to double
:
double func(short x) {
// rest all same
will give 8
as output.
sizeof(foo)
tries really hard to discover the size of an expression at compile time:
6.5.3.4:
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 short: variable length arrays, run at runtime. (Note: Variable Length Arrays are a specific feature -- not arrays allocated with malloc(3)
.) Otherwise, only the type of the expression is computed, and that at compile time.
The execution cannot happen during compilation. So ++i
/i++
will not happen. Also sizeof(foo())
will not execute the function but return correct type.
sizeof
is a compile-time builtin operator and is not a function. This becomes very clear in the cases you can use it without the parenthesis:
(sizeof x) //this also works
From the C99 Standard (the emphasis is mine)
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.
As the operand of sizeof
operator is not evaluated, you can do this:
int f(); //no definition, which means we cannot call it
int main(void) {
printf("%d", sizeof(f()) ); //no linker error
return 0;
}
Online demo : http://ideone.com/S8e2Y
That is, you don't need define the function f
if it is used in sizeof
only. This technique is mostly used in C++ template metaprogramming, as even in C++, the operand of sizeof
is not evaluated.
Why does this work? It works because the sizeof
operator doesn't operate on value, instead it operates on type of the expression. So when you write sizeof(f())
, it operates on the type of the expression f()
, and which is nothing but the return type of the function f
. The return type is always same, no matter what value the function would return if it actually executes.
In C++, you can even this:
struct A
{
A(); //no definition, which means we cannot create instance!
int f(); //no definition, which means we cannot call it
};
int main() {
std::cout << sizeof(A().f())<< std::endl;
return 0;
}
Yet it looks like, in sizeof
, I'm first creating an instance of A
, by writing A()
, and then calling the function f
on the instance, by writing A().f()
, but no such thing happens.
Demo : http://ideone.com/egPMi
Here is another topic which explains some other interesting properties of sizeof
: