The sizeof Operator in C
The C language provides a variety of fundamental types for storing numeric data and characters. Furthermore, as we will see, in C it is also possible to create arrays, strings and composite data structures.
According to the C language standard, only the char type has a known and fixed size always at 1 byte. All other fundamental types, and those derived from them, can have different sizes depending on the compiler, processor and operating system on which the program is executed.
For this reason, and especially to make your own code written in C portable across different platforms, it is important to know the size of a data type or a variable. To do this, the C language provides the sizeof operator.
The sizeof Operator
In C language, situations often arise where it is necessary to know the size of a data type or a variable. In particular, it is often necessary to know how much memory in terms of bytes is required to store a data type.
To solve this problem, the C language provides the sizeof operator.
The syntax of the operator is as follows:
sizeof(type_name)
The result of the above expression is an unsigned integer that represents the number of bytes required to store a value of that type.
In general, the C language standard ensures that the size of a char is always equal to one byte. Therefore, the following expression will always be worth 1:
/* sizeof(char) is always 1 */
sizeof(char)
Instead, the result of the sizeof operator applied to other types can return different values depending on the compiler, processor and operating system. This is, in essence, the reason for its existence: to allow the programmer to write code that is independent of the platform on which it is executed.
Thanks to the sizeof operator we can determine the size of a data type or a variable dynamically, without having to make assumptions about the platform on which the program is executed.
Suppose we want to write a program that prints to screen the size of the various integer types provided by the C language. We can do it this way:
#include <stdio.h>
int main() {
printf("Size of a char: %lu byte\n", sizeof(char));
printf("Size of a short: %lu byte\n", sizeof(short));
printf("Size of an int: %lu byte\n", sizeof(int));
printf("Size of a long: %lu byte\n", sizeof(long));
printf("Size of a long long: %lu byte\n", sizeof(long long));
return 0;
}
If we try to compile and execute this program on a 64-bit machine, for example on a machine with an Intel x86_64 processor and a Linux operating system, we will get an output similar to the following:
Size of a char: 1 byte
Size of a short: 2 byte
Size of an int: 4 byte
Size of a long: 8 byte
Size of a long long: 8 byte
As we can see, the size of a char is always 1 byte, while the size of the other integer types varies depending on the platform on which the program is executed.
sizeof Operator
The sizeof operator is a unary operator that returns the size in bytes of a data type.
The syntax of the sizeof operator is as follows:
sizeof(type_name)
The result of the expression sizeof(type_name) is an unsigned integer that represents the number of bytes required to store a value of that type.
In general, the sizeof operator is different from other operators in the sense that often its result is known at compile time when applied to a type.
In fact, many compilers optimize the code and calculate its value at compile time, rather than at runtime. This means that the sizeof operator is very efficient and does not involve any computational cost at runtime.
sizeof Applied to Variables and Expressions
The sizeof operator is very general in its applicability.
In fact, in C language it is possible to apply it not only to type names, but also to variables, constants and expressions.
If sizeof is applied to a variable, its result will be the size in bytes of the type to which the variable belongs.
For example, if we have a variable x of type int, we can write:
int x;
printf("Size of x: %lu byte\n", sizeof(x));
The result of this expression will be the size in bytes of an int on the platform on which the program is executed.
Similarly, the operator can be applied to an expression. In this case, the result will be the size in bytes of the data type that the expression returns.
For example, if we have an expression x + y, we can write:
int x, y;
/* ... */
printf("Size of x + y: %lu byte\n", sizeof(x + y));
In the above example, the result of the expression x + y is an int, so the result of the sizeof operator will be the size in bytes of an int.
When sizeof is applied to an expression, the compiler calculates the type of the expression and returns the size in bytes of that type.
Furthermore, when applied to a variable or an expression, the sizeof operator does not require parentheses. We can, in fact, write:
int x;
sizeof x;
sizeof Operator Applied to Variables and Expressions
The sizeof operator can also be applied to variables and expressions.
If applied to a variable the syntax is as follows:
sizeof(variable)
In this case the result will be the size in bytes of the type to which the variable belongs.
If applied to an expression the syntax is as follows:
sizeof(expression)
In this case the result will be the size in bytes of the data type that the expression returns.
In both cases the parentheses can be omitted:
sizeof variable;
sizeof expression;
But if the parentheses are omitted you must pay attention to operator precedence.
Always Use Parentheses with sizeof
Although the sizeof operator applied to an expression or a variable does not require parentheses, it is always good practice to include them.
In fact, take the following expression:
sizeof x + y;
One might mistakenly think that the result of this expression is sizeof applied to the addition of x and y. In reality, the addition operator has lower priority than sizeof, so the result of this expression will be sizeof x added to y, that is, it will be interpreted as:
(sizeof x) + y;
Therefore, to get the desired result, it is always better to include parentheses:
sizeof(x + y);
The size_t Type
An important clarification must be made regarding the data type that the sizeof operator returns.
We said that it returns an unsigned integer. To be precise, the type returned by the sizeof operator is called size_t.
The size_t type is a type defined by the C language standard library (header <stddef.h>) and represents the size of an object in bytes.
It is, in fact, an unsigned integer. However, the compiler's C standard library guarantees that the size of size_t is sufficient to represent the size of any object in memory.
The consequence of what was said above is that size_t is a platform-specific data type. In other words, the size of size_t can vary depending on the compiler, processor and operating system on which the program is executed.
However, we can expect that, for example, on a 32-bit processor that is capable of addressing 4 GB of memory, the size of size_t is 4 bytes. Instead, on a 64-bit processor, the size of size_t will be 8 bytes.
In general, when we work with small amounts of memory, there is no problem in casting size_t to unsigned long or unsigned long long.
The size_t Type
The size_t type is an unsigned integer type defined by the C standard library, in the header <stddef.h>, capable of representing the size of an object in bytes on a specific platform.
The result of the sizeof operator is of type size_t.
The size of size_t can vary depending on the compiler, processor and operating system on which the program is executed.
The C standard guarantees, however, that the size of size_t is sufficient to represent the size of any object in memory.
size_t and printf
We said that we can always cast size_t to unsigned long or unsigned long long. So, if we want to use the printf function to print a value of type size_t that represents a quantity of memory we can use the format specifiers %lu or %llu.
For example, if we want to print the size of an int we can write:
printf("Size of an int: %lu byte\n", sizeof(int));
In C99, however, a specific format specifier was introduced for printing values of type size_t. This format specifier is %zu.
So, we can write:
printf("Size of an int: %zu byte\n", sizeof(int));
Format Specifier %zu
The format specifier %zu was introduced in C99 to print values of type size_t:
#include <stddef.h>
size_t size;
printf("Size: %zu byte\n", size);
In Summary
In this lesson we introduced an important operator of the C language: sizeof.
We saw that:
- The
sizeofoperator returns the size in bytes of a data type. - The
sizeofoperator can be applied to type names, variables and expressions. - The result of the
sizeofoperator is of typesize_t, a platform-specific type. size_tis an unsigned integer type defined by the C standard library.size_tis capable of representing the size of any object in memory.- We can use
size_twith theprintffunction using the format specifier%zu.
The importance of sizeof will be evident when we tackle more advanced topics, such as dynamic memory allocation and manipulation of arrays and strings.