Table of Contents
What is the sizeof operator?
The sizeof
operator, returns the size of an expression, or of an object type in C
. An expression is for example 1 + 2
, an object is any region of memory, and a type is for example int
. The value returned by the sizeof
operator, is of type size_t
, and its unit is byte.
sizeof( Type ) /* When using sizeof with an object type such as an int , the parenthesis () must be used .*/ sizeof expression sizeof( expression ) /* When the sizeof operator is used with an expression, the parenthesis () can or cannot be used .*/
size_t
is an unsigned integer type, which is defined in the stddef.h
header. It can hold any value returned by the sizeof
operator, and has a min value of 0
, and a max value of the largest value, that can be returned by the sizeof
operator. size_t
can for example be defined as:
typedef unsigned long size_t;
The sizeof
operator returns 1
, meaning 1
byte, when used with the char
, unsigned char
, or signed char
types.
#include <stdio.h> int main( int argc, char * argv [ ] ){ printf( "sizeof( char ) is: %lu\n", sizeof( char ) ); /*output: sizeof( char ) is: 1 */ return 0;}
The number of bits in a char
, is defined in the limits.h header, using the macro CHAR_BIT
.
#define CHAR_BIT 8
The following example illustrates, how to get the number of bits for other types.
#include <stdio.h> /* include the stdio.h header, in order to use printf, to print formatted strings .*/ #include <limits.h> /* include the limits.h header, to use CHAR_BIT, which defines the number of bits, that the char type can have .*/ int main( int argc, char * argv[ ] ) { printf( "sizeof( int ) is: %lu bytes\n", sizeof( int )); /* output: sizeof( int ) is: 4 bytes .*/ printf( "size of int in bits is: %lu bits\n", sizeof( int ) * CHAR_BIT ); /* output: size of int in bits is: 32 bits .*/ return 0;}
sizeof and structures
When sizeof
is used with a structure, it returns the size of the elements in this structure, with any padding. Padding will happen, when the size of the structure is not a multiple of the size of the largest element in this structure.
A structure is padded with bits, that don’t have any specific value, till it has a size which is a multiple of the largest element in this structure. Padding happens to have faster access to the structure elements, and because sometimes some cpu architecture don’t support access to non aligned memory.
#include <stdio.h> /* include the stdio header to use the printf function .*/ struct aPaddedStruct{ char aChar; // aChar has a size of 1 int anInt; /* anInt has a size of 4 bytes .*/ }; /* The size of aPaddedStruct is 8 instead of 5, since the size of the largest element in this struct is 4 bytes .*/ int main( int argc , char * argv[ ] ){ printf( "sizeof( struct aPaddedStruct ) is: %lu", sizeof( struct aPaddedStruct )); // sizeof( struct aPaddedStruct ) is: 8 return 0; }
If the last element of a structure is an array, which size is not defined, then sizeof
will return the size of the structure, without the array size.
#include<stdio.h> /* include the stdio header, to use the printf function .*/ struct aStruct{ short aShort; /* size of short is 2 bytes .*/ char aCharOne; // size of char is 1 char aCharTwo; // size of char is 1 int anIntArray[ ]; /* anIntArray doesn't have a size, because it does not define the number of elements it has.*/ }; // size of aStruct is 4 int main( int argc, char *argv[ ] ){ printf( "sizeof( aStruct ) is: %lu", sizeof( struct aStruct )); /*output : sizeof( aStruct ) is: 4 */ return 0; }
sizeof and unions
sizeof
returns the size of the largest element in a union
.
#include <stdio.h> /* include the stdio header, to use the printf function .*/ union aUnion{ char aChar; // size of char is 1 int anInt; // size of int is 4 long double aLongDouble; /*size of long double is 16 .*/ }; /* union aUnion will have the size of its largest element, it is aLongDouble, which is a long double, as such it has a size of 16 .*/ int main( int argc, char * argv[ ] ){ printf( "sizeof( union aUnion ) is: %lu" ,sizeof( union aUnion )); /* output: sizeof( union aUnion ) is: 16 .*/ return 0;}
A compiler might add padding to a union
, so that its size, will be a multiple of the size of the largest element, in this union. This is used to allow faster access, or because some cpu architecture, don’t allow access to non aligned boundaries.
#include <stdio.h> /* include the stdio header, to use the printf function .*/ struct _aStruct{ int anIntOne; // size of an int is 4 short aShort; // size of a short is 2 int anIntTwo; /* size of an int is 4 .*/ }; /* The size of _aStruct is 12, since it is padded to the size of its largest element, which is an int .*/ union aUnion{ struct _aStruct aStruct; // size of struct _aStruct is 12 long aLong; /* size of long is 8 .*/ }; /* The size of the largest element in this union is long. The union is padded to the size of its largest element, hence it has a size of 16 .*/ int main( int argc, char * argv[ ] ){ printf( "The size of aUnion is: %lu\n", sizeof( union aUnion )); /*output: the size of aUnion is: 16 */ return 0;}
sizeof and arrays
When using sizeof
with an array, it will return the size of all the elements in the array.
#include <stdio.h> /* include the stdio header, to use the printf function .*/ int main( int argc, char * argv[ ] ){ int anIntArray[ 22 ]; /* anIntArray has a size of the size of the int type, multiplied by 22. so it has a size of 4 * 22 = 88 bytes .*/ printf( "sizeof( anIntArray ) is: %lu\n" , sizeof( anIntArray )); // sizeof( anIntArray ) is: 88 char aCharArray[ 3 ]; /* aCharArray has a size of the size of the char type, multiplied by 3 . so it has a size of 1 * 3 = 3 bytes .*/ printf( "sizeof( aCharArray ) is: %lu\n" , sizeof( aCharArray )); // sizeof( aCharArray ) is: 3 return 0;}
sizeof
can be used to calculate the number of elements in an array, by dividing the size of the array, by the size of an element in the array.
#include <stdio.h> /* include the stdio header, to use the printf function .*/ int main( int argc, char * argv[ ] ){ short aShortArray[ 4 ]; /* aShortArray has a size of the size of the short type, multiplied by 4, so it has a size of 2 * 4 = 8 .*/ printf( "Number of elements in the array is: %lu\n", sizeof( aShortArray ) / sizeof( aShortArray[ 0 ] )); /* sizeof( aShortArray ) is equal to sizeof( short ) * 4 sizeof( aShortArray[ 0 ] ) is equal to sizeof( short ) hence sizeof( aShortArray ) / sizeof( aShortArray[ 0 ] ) = number of elements in the array output: Number of elements in the array is: 4 .*/ return 0;}
sizeof and pointers
A pointer is simply an address which is stored in memory, as such it has a size. The sizeof
operator, can be used to get the size of a pointer. There is no defined size of a pointer in C
, it is defined by the implementation, usually on a 32
bits machine, a pointer has a size of 32
bits, and on a 64
bits machine, a pointer has a size of 64
bits.
#include <stdio.h> /* include the stdio header, to use the printf function .*/ int main(int argc, char * argv[ ]){ printf("sizeof( void * ) is %lu\n", sizeof (void * )); // sizeof( void * ) is 8 printf( "sizeof( char * ) is %lu\n", sizeof( char * )); // sizeof( char * ) is 8 return 0;}
sizeof and other object types
An object is just a memory region, so it has an allocated size. The object types in C
are:
- integer types, such as int, short, enum…
- floating types, such as float, double, long double.
- structures.
- unions.
- arrays.
- pointers.
- atomic types.
#include <stdio.h> /* include the stdio header, to use the printf function .*/ #include <stdatomic.h> /* include the stdatomic header, to access the atomic types .*/ enum Binary{ zero, one }; /* define the enum Binary, an enum is an integer of the type int .*/ struct Boolean{ char _cBool; unsigned char _iBool; } true = {'T', 1}, false = {'F', 0}; /* define a Boolean structure. the Boolean structure defines that a boolean, has a char and an int representation. Two variables were initialized from this structure, true and false .*/ union BooleanOrBinary { enum Binary binary; struct Boolean boolean;}; /* Define a union BooleanOrBinary, to store a boolean value , as either of type struct Boolean or as of type enum Binary .*/ /* Print the sizeof object types on a given machine. The sizeof a char is always 1. The sizeof object types are a multiple of the sizeof a char. The size of objects types might vary from one machine to another .*/ int main( ){ printf( "sizeof( char ) is : %lu byte\n", sizeof( char )); // sizeof( char ) is: 1 byte printf( "sizeof( short ) is : %lu byte\n", sizeof( short )); // sizeof( short ) is: 2 byte printf( "sizeof( int ) is: %lu byte\n", sizeof( int )); // sizeof( int ) is: 4 byte printf("sizeof( long int ) is: %lu byte\n", sizeof( long int )); // sizeof( long int ) is: 8 byte printf( "sizeof( long long int ) is: %lu byte\n", sizeof( long long int )); // sizeof(long long int) is : 8 byte printf( "sizeof( float ) is: %lu byte\n", sizeof( float )); // sizeof( float ) is: 4 byte printf( "sizeof( double ) is: %lu byte\n", sizeof( double )); // sizeof( double ) is: 8 byte printf( "sizeof( long double ) is: %lu byte\n", sizeof( long double )); // sizeof( long double ) is: 16 byte printf( "sizeof( enum binary ) is: %lu byte\n", sizeof( enum Binary )); // sizeof( enum binary ) is: 4 byte printf( "sizeof( struct Boolean ) is : %lu byte\n", sizeof( struct Boolean )); // sizeof( struct Boolean ) is: 2 byte printf( "sizeof( union BooleanOrBinary ) is: %lu byte\n", sizeof( union BooleanOrBinary )); // sizeof( union BooleanOrBinary ) is: 4 byte printf( "sizeof( void * ) is %lu byte\n", sizeof( void * )); // sizeof( void * ) is 8 byte printf( "sizeof( int[ 1 ] ) is: %lu byte\n", sizeof( int[ 1 ] )); // sizeof( int[ 1 ] ) is: 4 byte printf( "sizeof( atomic_int_fast32_t ) is: %lu byte\n", sizeof( atomic_int_fast32_t )); // sizeof( atomic_int_fast32_t ) is: 4 byte return 0; }
sizeof and expressions
sizeof expression sizeof( expression )
An expression is simply a combination of operands and operators, whatever these operand or operators are. When using the sizeof
operator with an expression, the parenthesis ()
can be used or skipped .
#include <stdio.h> /* include the stdio header, to use the printf function .*/ int sum( int x, int y ){ /* return the sum of x and y */ return x + y; } int main( int argc, char * argv[ ] ){ int anInt = 1; printf( "sizeof anInt is: %lu \n", sizeof anInt ); // sizeof anInt is: 4 double aDouble = 3.0; printf( "sizeof aDouble is: %lu \n", sizeof aDouble ); // sizeof aDouble is: 8 printf( "sizeof( aDouble + anInt ) is: %lu \n", sizeof( aDouble + anInt )); // sizeof( aDouble + anInt ) is: 8 printf( "sizeof( 3.0f + 1 ) is: %lu \n", sizeof( 3.0f + 1 )); /* 3.0f is a float 3.0f + 1 = 4.0f 4.0f is a float sizeof( float ) is 4 Output: sizeof (3.0 + 1) is: 4 .*/ printf( "sizeof sum( 1, 5 ) is: %lu \n", sizeof sum( 1, 5 )); // sizeof sum( 1, 5 ) is: 4 printf( "sizeof 100 is: %lu \n", sizeof 100 ); // sizeof 100 is: 4 return 0;}
sizeof cannot be applied?
The sizeof
operator, cannot be applied to a non object type, such as a function, or to an incomplete type. An incomplete type, is a type which is declared but not yet defined, or a type which doesn’t have a size, such as the void type.
struct incompleteTypeStruct; /* struct incompleteTypeStruct is declared but is not yet defined , as such it is an incomplete type .*/ enum incompleteTypeEnum; /* enum incompleteTypeEnum is declared but is not yet defined, as such it is an incomplete type .*/ int anIntarray[ ]; /* anIntarray size is not defined, as such it is an incomplete type .*/ int main( int argc, char * argv[ ] ){ sizeof( struct incompleteTypeStruct ); sizeof( enum incompleteTypeEnum ); sizeof( anIntarray ); sizeof( void ); /* These statements will cause an error, since they are trying to get the size of incomplete types .*/ return 0;}