Difference between revisions of "cpp/language/sizeof"
(Example didn't include the important fact that the sizeof (array) changes to sizeof (pointer) when the array is passed a function G(int[10]). Also didn't mention that sizeof F(a) does not evaluate F. Added these.) |
m (Changed spacing to make the code easier to read) |
||
Line 57: | Line 57: | ||
struct CharIntChar { char c; int i; char c2; }; | struct CharIntChar { char c; int i; char c2; }; | ||
struct CharShortChar { char c; short s; char c2; }; | struct CharShortChar { char c; short s; char c2; }; | ||
− | + | ||
int* F(int a[10]); | int* F(int a[10]); | ||
void G(int a[10]); | void G(int a[10]); | ||
Line 86: | Line 86: | ||
<< "\nG) sizeof(CharIntChar) " << sizeof(CharIntChar) | << "\nG) sizeof(CharIntChar) " << sizeof(CharIntChar) | ||
<< "\nH) sizeof(CharShortChar) " << sizeof(CharShortChar) << '\n'; | << "\nH) sizeof(CharShortChar) " << sizeof(CharShortChar) << '\n'; | ||
− | + | ||
int a[10]; | int a[10]; | ||
std::cout | std::cout | ||
Line 97: | Line 97: | ||
<< "\nN) sizeof F(a): " << sizeof F(a); // F(a) unevaluated | << "\nN) sizeof F(a): " << sizeof F(a); // F(a) unevaluated | ||
assert(sizeof F(a) == sizeof(int*)); // F(a) is an unevaluated expressions | assert(sizeof F(a) == sizeof(int*)); // F(a) is an unevaluated expressions | ||
− | std::cout << "\nO) Inside main()" << std::boolalpha; | + | std::cout << "\nO) Inside main()\n " << std::boolalpha; |
− | std::cout << " | + | std::cout << "std::is_same<decltype(a),int[10]> " |
− | << std::is_same<decltype(a),int[10]>::value | + | << std::is_same<decltype(a),int[10]>::value << "\n " |
− | + | << "std::is_same<decltype(a),int*> " | |
− | << std::is_same<decltype(a),int*>::value | + | << std::is_same<decltype(a),int*>::value |
<< "\n sizeof a == sizeof(int[10]) == " << sizeof(int[10]); | << "\n sizeof a == sizeof(int[10]) == " << sizeof(int[10]); | ||
assert(sizeof a == sizeof(int[10])); | assert(sizeof a == sizeof(int[10])); | ||
Line 112: | Line 112: | ||
} | } | ||
void G(int a[10]) { // a is a pointer and sizeof(a) == sizeof(int*) != sizeof(int[10]) | void G(int a[10]) { // a is a pointer and sizeof(a) == sizeof(int*) != sizeof(int[10]) | ||
− | std::cout << "\nP) Inside void G(int a[10])" | + | std::cout << "\nP) Inside void G(int a[10])\n " |
− | << " | + | << "std::is_same<decltype(a),int[10]> " |
− | << std::is_same<decltype(a),int[10]>::value | + | << std::is_same<decltype(a),int[10]>::value << "\n " |
− | + | << "std::is_same<decltype(a),int*> " | |
− | << std::is_same<decltype(a),int*>::value | + | << std::is_same<decltype(a),int*>::value |
<< "\n sizeof a == sizeof(int*) == " << sizeof(int*) << '\n'; | << "\n sizeof a == sizeof(int*) == " << sizeof(int*) << '\n'; | ||
} | } |
Revision as of 18:29, 26 November 2022
Queries size of the object or type.
Used when actual size of the object must be known.
Contents |
Syntax
sizeof( type )
|
(1) | ||||||||
sizeof expression
|
(2) | ||||||||
Both versions are constant expressions of type std::size_t.
Explanation
Notes
Depending on the computer architecture, a byte may consist of 8 or more bits, the exact number being recorded in CHAR_BIT.
The following sizeof
expressions always evaluate to 1:
- sizeof(char)
- sizeof(signed char)
- sizeof(unsigned char)
|
(since C++17) |
|
(since C++20) |
sizeof
cannot be used with function types, incomplete types, or bit-field lvalues(until C++11)glvalues(since C++11).
When applied to a reference type, the result is the size of the referenced type.
When applied to a class type, the result is the number of bytes occupied by a complete object of that class, including any additional padding required to place such object in an array. The number of bytes occupied by a potentially-overlapping subobject may be less than the size of that object.
The result of sizeof
is always nonzero, even if applied to an empty class type.
When applied to an expression, sizeof
does not evaluate the expression, and even if the expression designates a polymorphic object, the result is the size of the static type of the expression. Lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversions are not performed. Temporary materialization, however, is (formally) performed for prvalue arguments: the program is ill-formed if the argument is not destructible.(since C++17)
Keywords
Example
The example output corresponds to a system with 64-bit pointers and 32-bit int.
#include <cassert> #include <iostream> #include <type_traits> struct Empty {}; struct Base { int a; }; struct Derived : Base { int b; }; struct Bit { unsigned bit: 1; }; struct CharChar { char c; char c2; }; struct CharCharInt { char c; char c2; int i; }; struct IntCharChar { int i; char c; char c2; }; struct CharIntChar { char c; int i; char c2; }; struct CharShortChar { char c; short s; char c2; }; int* F(int a[10]); void G(int a[10]); int main() { Empty e; Derived d; Base& b = d; [[maybe_unused]] Bit bit; std::cout << "1) sizeof empty class: " << sizeof e << "\n2) sizeof pointer: " << sizeof &e // << "\n3) sizeof function: " << sizeof(void()) // error // << "\n4) sizeof incomplete type: " << sizeof(int[]) // error // << "\n5) sizeof bit field: " << sizeof bit.bit // error << "\n6) sizeof(Bit) class: " << sizeof(Bit) << "\n7) sizeof the Derived class: " << sizeof d << "\n8) sizeof the Derived through Base: " << sizeof b << "\n9) sizeof(unsigned) " << sizeof(unsigned) << "\nA) sizeof(int) " << sizeof(int) << "\nB) sizeof(short) " << sizeof(short) << "\nC) sizeof(char) " << sizeof(char) << "\nD) sizeof(CharChar) " << sizeof(CharChar) << "\nE) sizeof(CharCharInt) " << sizeof(CharCharInt) << "\nF) sizeof(IntCharChar) " << sizeof(IntCharChar) << "\nG) sizeof(CharIntChar) " << sizeof(CharIntChar) << "\nH) sizeof(CharShortChar) " << sizeof(CharShortChar) << '\n'; int a[10]; std::cout << "\nArrays\nint a[10];" << "\nI) sizeof(int[10]) array of 10 int: " << sizeof(int[10]) << "\nJ) sizeof a array of 10 int: " << sizeof a << "\nK) sizeof *a: " << sizeof *a << "\nL) length of array of 10 int: " << ((sizeof a) / (sizeof *a)) << "\nM) length of array of 10 int (2): " << ((sizeof a) / (sizeof a[0])) << "\nN) sizeof F(a): " << sizeof F(a); // F(a) unevaluated assert(sizeof F(a) == sizeof(int*)); // F(a) is an unevaluated expressions std::cout << "\nO) Inside main()\n " << std::boolalpha; std::cout << "std::is_same<decltype(a),int[10]> " << std::is_same<decltype(a),int[10]>::value << "\n " << "std::is_same<decltype(a),int*> " << std::is_same<decltype(a),int*>::value << "\n sizeof a == sizeof(int[10]) == " << sizeof(int[10]); assert(sizeof a == sizeof(int[10])); G(a); } int* F(int a[10]) { std::cout << "sizeof F(a) does not evaluate F(). This will not be printed.\n"; abort(); // This will not be called return a; } void G(int a[10]) { // a is a pointer and sizeof(a) == sizeof(int*) != sizeof(int[10]) std::cout << "\nP) Inside void G(int a[10])\n " << "std::is_same<decltype(a),int[10]> " << std::is_same<decltype(a),int[10]>::value << "\n " << "std::is_same<decltype(a),int*> " << std::is_same<decltype(a),int*>::value << "\n sizeof a == sizeof(int*) == " << sizeof(int*) << '\n'; }
Possible output:
1) sizeof empty class: 1 2) sizeof pointer: 8 6) sizeof(Bit) class: 4 7) sizeof the Derived class: 8 8) sizeof the Derived through Base: 4 9) sizeof(unsigned) 4 A) sizeof(int) 4 B) sizeof(short) 2 C) sizeof(char) 1 D) sizeof(CharChar) 2 E) sizeof(CharCharInt) 8 F) sizeof(IntCharChar) 8 G) sizeof(CharIntChar) 12 H) sizeof(CharShortChar) 6 Arrays int a[10]; I) sizeof(int[10]) array of 10 int: 40 J) sizeof a array of 10 int: 40 K) sizeof *a: 4 L) length of array of 10 int: 10 M) length of array of 10 int (2): 10 N) sizeof F(a): 8 O) Inside main() std::is_same<decltype(a),int[10]> true std::is_same<decltype(a),int*> false sizeof a == sizeof(int[10]) == 40 P) Inside void G(int a[10]) std::is_same<decltype(a),int[10]> false std::is_same<decltype(a),int*> true sizeof a == sizeof(int*) == 8
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1122 | C++98 | result type of sizeof (std::size_t) was circularly defined | it is defined in the same way as in C |
CWG 1553 | C++11 | sizeof could be used with bit-field xvalues
|
prohibited |
See also
alignof operator(C++11)
|
queries alignment requirements of a type |
sizeof... operator(C++11)
|
queries the number of elements in a parameter pack |
C documentation for sizeof
|