The sizeof Operator in C and C++
Textbooks rarely make good use of the sizeof
operator in C (and C++). The syntax is
sizeof ( type )
and
sizeof variable
That is, in order to get the size of a variable, including an array, the parenthesis are not necessary. I personally find them a visual distraction, unless of course the operand is a type, like sizeof ( int )
.
Let’s look at a concrete example of using sizeof
without parenthesis. In this example, we’re preparing an error message for display on screen.
char buffer[ 1024 ]; /* Arbitrary size of the buffer. */ snprintf( buffer, sizeof buffer, "Unable to initialize SDL: %s", SDL_GetError() );
Because we’re using sizeof buffer
in the snprintf()
call we don’t have to worry about mistakes, or out of sync constants, and we don’t have to #define BUFFER_SIZE 1024
to use the same size in both definition of the buffer
and call to snprintf()
.
Note to Windows programmers. The snprintf()
function isn’t documented to always terminate the string with zero until Visual Studio 2015 and Windows 10. Programmers on the Windows platform might want to add an explicit zero termination to account for older compilers and systems. That can be done with buffer[ sizeof buffer - 1 ] = '\0'
.
The trick here is that we defined buffer
as an array. If we had instead used malloc()
to allocate the buffer, we would have to add the size of the buffer explicitly, like so,
char *buffer = malloc( 1024 ); if ( !buffer ) exit( 1 ); snprintf( buffer, 1024, "Unable to initialize SDL: %s", SDL_GetError() );
and we would have to explicitly check the return value from malloc()
as is written about at length in why it is important to check what the malloc function returned. If we had instead used sizeof buffer
here, we’d have gotten 4 on a 32bit system, and 8 on a 64bit system — which is totally not the value we need.
The snprintf()
function returns how many characters have been or would be printed. In our case we don’t care if the message the user receives gets truncated, so we don’t check its return value.
It is worth noting that when a character literal is used, it matters whether the literal is declared as a pointer or array. That is, given
char *foo = "Error string.", bar[] = "Another error string.";
then sizeof foo
will give us 4 on 32bit system, 8 on a 64bit system, while sizeof bar
is 22 or the length of the string including the terminating zero byte.
Literals
The sizeof
operator applies to literals also without parenthesis, and it’s instructive to test it on some literal combinations on a given system. For example, this program
#include <stdio.h> int main( int argc, char *argv[] ) { printf( "sizeof 0 = %zu\n", sizeof 0 ); // int printf( "sizeof 0l = %zu\n", sizeof 0l ); // long printf( "sizeof 0ll = %zu\n", sizeof 0ll ); // long long printf( "sizeof NULL = %zu\n", sizeof NULL ); // pointer printf( "sizeof 0.0 = %zu\n", sizeof 0.0 ); // double printf( "sizeof 0.0f = %zu\n", sizeof 0.0f ); // float printf( "sizeof \"foo\" = %zu\n", sizeof "foo" ); // string size including zero terminator return 0; }
run an a 64bit Linux and compiled with clang
, gives
sizeof 0 = 4 sizeof 0l = 8 sizeof 0ll = 8 sizeof NULL = 8 sizeof 0.0 = 8 sizeof 0.0f = 4 sizeof "foo" = 4
and none of that should be surprising.
Contact
The author can be reached at johann@myrkraverk.com.
Updates
Added the section on literals.