Question
I am compiling the following C program in Dev-C++ on Windows:
#include <stdio.h>
int main(void) {
int x = 5;
printf("%d and ", sizeof(x++));
printf("%d\n", x);
return 0;
}
I expected x to become 6 after the call containing sizeof(x++), but the program prints:
4 and 5
Why does x not increment when used inside sizeof?
Short Answer
By the end of this page, you will understand that sizeof usually determines the size of a type without evaluating its expression operand. That is why sizeof(x++) returns the size of int, but the side effect of x++ never happens, so x stays 5. You will also learn the important exception involving variable length arrays.
Concept
In C, sizeof is an operator that tells you how many bytes a type or object occupies.
For example:
sizeof(int)
sizeof x
sizeof(x)
all ask for a size in bytes.
The key idea is this:
sizeofusually does not evaluate the expression you put inside it.- It only uses that expression to determine its type.
- Since the expression is not executed, any side effects inside it do not happen.
That is exactly what happens here:
sizeof(x++)
x++ is a post-increment expression. Normally, evaluating it would:
- produce the current value of
x - increment
xafterward
But inside sizeof, the expression is typically not evaluated at all. C only checks the type of x++, which is int, and returns sizeof(int).
So if int is 4 bytes on your system, the result is 4, and x remains 5.
Why this matters
This is important because many C operators and constructs look like they "run" code, but some operate only at the type level or compile-time-like level. Understanding this helps you avoid bugs and write clearer code.
Important exception
There is one important exception in C: variable length arrays (VLAs). When sizeof is applied in situations involving VLAs, the expression may need to be evaluated because the size is determined at runtime.
For ordinary expressions like sizeof(x++) where x is an int, no increment happens.
Mental Model
Think of sizeof as asking a librarian:
"How big is a book of this category?"
The librarian does not need to read the whole book to answer. They just look at the label or classification.
In the same way, sizeof(x++) does not "run" the increment. It simply looks at the expression and says:
x++has typeint- an
intis 4 bytes here
So sizeof answers 4 and never performs the ++.
Another way to think about it:
x++is an action with a side effectsizeof(...)usually asks only for type/size information- if no action is executed, no side effect occurs
Syntax and Examples
Core syntax
sizeof(type)
sizeof expression
Examples:
sizeof(int)
sizeof(double)
sizeof x
sizeof(x + 1)
Example 1: Simple variable
#include <stdio.h>
int main(void) {
int x = 5;
printf("%zu\n", sizeof(x));
return 0;
}
This prints the number of bytes used by x's type, which is usually the size of int.
Example 2: Expression inside sizeof
#include <stdio.h>
int main(void) {
int x = 5;
printf("%zu\n", sizeof(x + 10));
printf("%d\n", x);
return 0;
}
x + 10 is not evaluated. sizeof just determines the type of the expression, which is still int here.
Example 3: Post-increment inside sizeof
#include <stdio.h>
int main(void) {
int x = 5;
printf("%zu and %d\n", sizeof(x++), x);
return 0;
}
Output is typically:
4 and 5
Why?
sizeof(x++)asks for the size of the expression's type- it does not execute
x++ xis still5
About printing sizeof
The result type of sizeof is size_t, so the correct format specifier is usually %zu:
printf("%zu\n", sizeof(x));
Using %d may work on some systems, but it is not the correct type-safe choice.
Step by Step Execution
Consider this program:
#include <stdio.h>
int main(void) {
int x = 5;
size_t s = sizeof(x++);
printf("size = %zu, x = %d\n", s, x);
return 0;
}
Step-by-step
1. int x = 5;
A variable x is created and initialized to 5.
2. size_t s = sizeof(x++);
C looks at x++ only to determine its type.
xis anintx++also has typeintsizeof(int)is usually4
So s gets the value 4.
What does not happen:
x++is not executedxis not incremented
So x is still 5.
3. printf("size = %zu, x = %d\n", s, x);
This prints something like:
size = 4, x = 5
Important takeaway
Even though x++ normally changes x, putting it inside sizeof prevents that normal evaluation in most cases.
Real World Use Cases
Understanding this behavior is useful in several practical situations.
1. Writing safe macros
C codebases often use macros that depend on sizeof:
#define ARRAY_BYTES(arr) (sizeof(arr))
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0]))
These work because sizeof can inspect types and sizes without evaluating expressions in the usual case.
2. Allocating memory
Developers often write:
int *p = malloc(10 * sizeof(*p));
This is useful because sizeof(*p) gives the size of the pointed-to type without dereferencing memory in the runtime sense.
3. Avoiding side-effect confusion
If you accidentally write code like this:
sizeof(i++)
expecting i to change, your program logic will be wrong. Understanding the rule helps you avoid subtle bugs.
4. Reading unfamiliar C code
In real projects, you will often see expressions placed inside sizeof for type-based sizing. Knowing that they are usually not evaluated helps you read code correctly.
Real Codebase Usage
In real C projects, sizeof is commonly used in patterns like these.
Type-safe allocation
int *arr = malloc(count * sizeof(*arr));
Why developers like this:
- it avoids repeating the type name
- if the variable type changes later, the
sizeofpart stays correct
Struct sizing
struct User *u = malloc(sizeof(*u));
This is clearer and less error-prone than manually writing the struct type again.
Array length macros
#define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0]))
This works for actual arrays, not pointers.
Guarding against logic mistakes
Experienced developers avoid writing expressions with side effects inside sizeof, even though they know those expressions are usually not evaluated. For example, they prefer not to write:
sizeof(x++)
because it is confusing to readers.
Instead, they keep sizeof expressions simple and side-effect free.
Validation and clarity
In production code, clarity matters. A developer reading:
sizeof(buffer)
immediately understands the intention. But reading:
sizeof(get_value())
may raise questions about whether get_value() runs. Keeping sizeof operands simple reduces confusion and maintenance cost.
Common Mistakes
1. Expecting side effects to happen
Broken expectation:
int x = 5;
size_t s = sizeof(x++);
printf("%d\n", x); // still 5, not 6
How to avoid it
Do not place increments, decrements, assignments, or function calls inside sizeof if you expect them to run.
2. Using the wrong printf format specifier
Broken code:
printf("%d\n", sizeof(x));
Why it is a problem:
sizeofreturnssize_t%dis forint
Better:
printf("%zu\n", sizeof(x));
3. Confusing arrays and pointers
Broken assumption:
void print_len(int arr[]) {
printf("%zu\n", sizeof(arr) / sizeof(arr[0]));
}
Inside a function parameter, arr is actually a pointer, not an array, so this does not give the array length.
4. Assuming sizeof(int) is always 4
Many systems use 4-byte int, but the C standard does not require it to always be 4.
Safer mindset:
sizeof(int)is implementation-dependent- check, do not assume
5. Forgetting the VLA exception
Most of the time, sizeof does not evaluate its operand. But with variable length arrays, runtime evaluation may be involved.
For beginners, the safe rule is:
- usually,
sizeofdoes not evaluate expressions - but VLAs are a special case worth remembering
Comparisons
sizeof vs normal evaluation
| Expression | Is it evaluated? | Side effects happen? | Result |
|---|---|---|---|
x++ | Yes | Yes | Old value of x, then increment |
sizeof(x++) | Usually no | No | Size of the type of x++ |
sizeof(int) | No runtime evaluation | No | Size of int |
sizeof on a type vs an expression
| Form | Example | Meaning |
|---|---|---|
sizeof(type) | sizeof(int) | Size of that type |
sizeof expression | sizeof x | Size of the expression's type |
sizeof(expression) | sizeof(x + 1) | Same idea, with parentheses for grouping |
sizeof vs strlen
These are often confused.
| Feature | sizeof | strlen |
|---|---|---|
| Works on | Types or objects | Null-terminated strings |
| Evaluates string contents? | No | Yes |
| Returns | Bytes occupied | Number of characters before \0 |
| Example | sizeof("cat") is often 4 | strlen("cat") is 3 |
sizeof with arrays vs pointers
| Case | Example | Typical result |
|---|---|---|
| Array | int a[10]; sizeof(a) | Total bytes of all 10 elements |
| Pointer | int *p; sizeof(p) | Size of the pointer itself |
This difference is very important in real C programs.
Cheat Sheet
Quick rules for sizeof
sizeofreturns the size in bytes.- The result type is
size_t. - Use
%zuto print asizeofresult. sizeofusually does not evaluate its expression operand.- Side effects inside
sizeofusually do not happen. - Exception: variable length arrays can require runtime evaluation.
Common forms
sizeof(int)
sizeof x
sizeof(x)
sizeof(x + 1)
Important example
int x = 5;
size_t s = sizeof(x++);
After this:
x == 5
because x++ was not evaluated.
Correct printing
printf("%zu\n", sizeof(x));
Good practice
Prefer clear operands:
sizeof(buffer)
sizeof(*ptr)
sizeof(struct Node)
Avoid confusing code like:
sizeof(i++)
sizeof(func())
Memory allocation pattern
int *p = malloc(n * sizeof(*p));
FAQ
Why does sizeof(x++) not change x in C?
Because sizeof usually does not evaluate its operand expression. It only determines the expression's type and returns that type's size.
Does sizeof ever evaluate its operand?
Usually no. The important exception is when variable length arrays are involved, because their size may need runtime evaluation.
What does sizeof(x++) actually return?
It returns the size in bytes of the type of x++. If x is an int, that is typically the same as sizeof(int).
Why did my program print 4 and 5?
4 is the typical size of int on your system, and 5 remains unchanged because x++ was not executed.
Should I use %d to print sizeof results?
No. The correct format specifier is %zu because sizeof returns size_t.
Is sizeof(int) always 4?
No. It is implementation-dependent. Many modern systems use 4-byte int, but the language standard does not guarantee that exact size.
Is sizeof a function?
No. It is an operator in C.
Can I safely put function calls inside sizeof?
They usually will not run, but doing so is often confusing. It is better style to avoid expressions with side effects inside sizeof.
Mini Project
Description
Build a small C program that reports the sizes of different types and expressions, while showing that side effects inside sizeof usually do not happen. This reinforces how sizeof works in practical code and helps you practice printing size_t correctly.
Goal
Create a program that compares normal expression evaluation with sizeof behavior and prints the results clearly.
Requirements
- Declare at least one
intvariable and one array. - Print the size of an
int, the size of the variable, and the size of the array. - Demonstrate that
x++increments normally outsidesizeof. - Demonstrate that
x++does not incrementxinsidesizeof. - Use the correct
printfformat specifier forsizeofresults.
Keep learning
Related questions
2D Array Loop Order and Cache Performance in C
Learn why swapping nested loops changes 2D array performance in C, using row-major memory layout, cache locality, and practical benchmarks.
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.