sizeof
creference sizeof operator
Queries size of the object or type
Used when actual size of the object must be known
NOTE: 在这篇文章中提及,
sizeof()
is a compile-time operator. 所以,它的实现依赖于编译信息;
Syntax
sizeof( type ) |
sizeof expression |
Both versions return a value of type size_t.
1) Returns the size, in bytes, of the object representation of type
2) Returns the size, in bytes, of the object representation of the type of expression. No implicit conversions are applied to expression.
Notes
Depending on the computer architecture, a byte may consist of 8 or more bits, the exact number provided as CHAR_BIT.
sizeof(char)
, sizeof(signed char)
, and sizeof(unsigned char)
always return 1.
sizeof
cannot be used with function types, incomplete types (including void
), or bit field lvalues.
NOTE:
下面演示了
sizeof
function type的例子:#include <stdio.h> int main(void) { printf("sizeof(void(void)) = %zu\n", sizeof(void(void))); // Error: function type printf("sizeof(char[]) = %zu\n", sizeof(char[])); // Error: incomplete type printf("sizeof main = %zu\n", sizeof main); // Error: Function type }
When applied to an operand that has structure or union type, the result is the total number of bytes in such an object, including internal and trailing padding. The trailing padding is such that if the object were an element of an array, the alignment requirement of the next element of this array would be satisfied, in other words, sizeof(T)
returns the size of an element of a T[]
array.
If type is a VLA type and changing the value of its size expression would not affect the result of sizeof
, it is unspecified whether or not the size expression is evaluated.
Except if the type of expression is a VLA, (since C99)expression is not evaluated and the sizeof
operator may be used in an integer constant expression.
NOTE: 上面对
sizeof
和VLA进行了描述,上面的描述是非常不直接的,在Why does sizeof(x++) not increment x?的回答A中有较好的描述:
sizeof
is a ***compile-time operator*, so at the time of compilationsizeof
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.*需要注意的是,C++不支持VLA
Number of elements in any array a including VLA (since C99) may be determined with the expression sizeof a / sizeof a[0]
. Note that if a
has pointer type (such as after array-to-pointer conversion of function parameter type adjustment), this expression would simply divide the number of bytes in a pointer type by the number of bytes in the pointed type.
NOTE: 关于"
a
has pointer type"的情况,在文章stackoverflow How do I use arrays in C++?#
5.3 Pitfall: Using the C idiom to get number of elements.中进行了详细的分析。
#include <stdio.h>
int main(void)
{
short x;
// type argument:
printf("sizeof(float) = %zu\n", sizeof(float));
printf("sizeof(void(*)(void)) = %zu\n", sizeof(void(*)(void)));
printf("sizeof(char[10]) = %zu\n", sizeof(char[10]));
// printf("sizeof(void(void)) = %zu\n", sizeof(void(void))); // Error: function type
// printf("sizeof(char[]) = %zu\n", sizeof(char[])); // Error: incomplete type
// expression argument:
printf("sizeof 'a' = %zu\n", sizeof 'a'); // type of 'a' is int
// printf("sizeof main = %zu\n", sizeof main); // Error: Function type
printf("sizeof &main = %zu\n", sizeof &main);
printf("sizeof \"hello\" = %zu\n", sizeof "hello"); // type is char[6]
printf("sizeof x = %zu\n", sizeof x); // type of x is short
printf("sizeof (x+1) = %zu\n", sizeof(x+1)); // type of x+1 is int
}
NOTE:上述程序的输出如下:
sizeof(float) = 4 sizeof(void(*)(void)) = 8 sizeof(char[10]) = 10 sizeof 'a' = 4 sizeof &main = 8 sizeof "hello" = 6 sizeof x = 2 sizeof (x+1) = 4
NOTE :
&main
中的&
是Member access operators,它返回的是一个pointer;NOTE : 关于
void(*)(void))
和void(void)
的理解,参看这篇文章:What does C expression ((void(*)(void))0)(); mean?
sizeof
and unevaluated expressions
在cppreference Expressions#Unevaluated expressions章节中,介绍了unevaluated expressions 的概念:
对于C++而言,由于它不支持VLA,所以在C++中,"the operands of sizeof
operator are expressions that are not evaluated "
对于C而言,需要分情况进行讨论:
- 如果expression是VLA,不是
- 如果expression不是VLA,则和C++相同
Why does sizeof(x++) not increment x?
Here is the code compiled in dev c++ windows:
#include <stdio.h>
int main() {
int x = 5;
printf("%d and ", sizeof(x++)); // note 1
printf("%d\n", x); // note 2
return 0;
}
I expect x
to be 6 after executing note 1. However, the output is:
4 and 5
Can anyone explain why x
does not increment after note 1?
A
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.
### Examples
#include <cstddef
#include <iostream
int main()
{
std::size_t n = sizeof(std::cout << 42);
std::cout << n << std::endl;
}
// g++ test.cpp
上述程序的输出为:
272
Why does sizeof(x++) not increment x?:
#include <stdio.h
int main()
{
int x = 5;
printf("%d and ", sizeof(x++)); // note 1
printf("%d\n", x); // note 2
return 0;
}
// gcc test.c
上述程序的输入:
4 and 5
https://stackoverflow.com/questions/8225776/why-does-sizeofx-not-increment-x/8225813#8225813
#include <stdio.h
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;
}
// gcc test.c
Why is sizeof considered an operator?
A
Because the C standard says so, and it gets the only vote.
As consequences:
- The operand of
sizeof
can be a parenthesised type,sizeof (int)
, instead of an object expression.
SUMMARY : 用于类型必须要要加上parentheses
-
The parentheses are unnecessary:
int a; printf("%d\n", sizeof a);
is perfectly fine. They're often seen, firstly because they're needed as part of a type cast expression, and secondly becausesizeof
has very high precedence, sosizeof a + b
isn't the same assizeof (a+b)
. But they aren't part of the invocation ofsizeof
, they're part of the operand. -
You can't take the address of
sizeof
. -
The expression which is the operand of
sizeof
is not evaluated at runtime (sizeof a++
does not modifya
).
SUMMARY : 关于这一点,参见下面的Why does sizeof(x++) not increment x?
- The expression which is the operand of sizeof can have any type except void, or function types. Indeed, that's kind of the point of sizeof.
A function would differ on all those points. There are probably other differences between a function and a unary operator, but I think that's enough to show why sizeof could not be a function even if there was a reason to want it to be.
A
It can be used as a compile-time constant, which is only possible if it's an operator rather than a function. For instance:
union foo {
int i;
char c[sizeof(int)];
};
Syntactically if it weren't an operator then it would have to be a preprocessor macro since functions can't take types as arguments. That would be a difficult macro to implement since sizeof
can take both types and variables as an argument.