sizeof operator in c

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;}