Question
I have a variable of type size_t, and I want to print it using printf(). Which format specifier should I use to print it portably?
On a 32-bit machine, %u appears to work. I compiled with:
g++ -g -W -Wall -Werror -ansi -pedantic
and there was no warning. However, when I compile the same code on a 64-bit machine, I get a warning.
size_t x = /* some value */;
printf("size = %u\n", x);
The compiler reports:
warning: format '%u' expects type 'unsigned int',
but argument 2 has type 'long unsigned int'
The warning goes away, as expected, if I change %u to %lu.
How can I write this code so that it compiles without warnings on both 32-bit and 64-bit machines?
As a possible workaround, I could cast the variable to a large enough integer type such as unsigned long and print it with %lu, but I would like to know whether there is a more portable solution.
Short Answer
By the end of this page, you will understand why size_t should not be printed with %u or %lu directly, and how to print it portably using the correct printf format specifier: %zu. You will also learn what size_t represents, why platform differences matter, and how to avoid common formatting mistakes in C.
Concept
size_t is an unsigned integer type used to represent sizes and counts of objects in memory. You commonly see it as the return type of sizeof(), and in standard library functions that work with array lengths, memory sizes, and buffer counts.
The important detail is that size_t is not guaranteed to be the same type on every platform:
- On one system, it might be
unsigned int - On another, it might be
unsigned long - On another, it could be a different unsigned integer type
Because printf() is a variadic function, it does not know the actual type of each argument unless the format string tells it correctly. That means the format specifier must match the argument type exactly.
Using %u assumes the argument is an unsigned int.
Using %lu assumes the argument is an unsigned long.
Neither is guaranteed to match size_t everywhere.
The portable solution in standard C is:
printf("%zu\n", value);
Here:
%zis the length modifier for
Mental Model
Think of size_t as a container label that changes depending on the machine.
You want to print the number inside the container. But printf() needs the correct label to know how to read it.
%usays: "This container is anunsigned int."%lusays: "This container is anunsigned long."%zusays: "This container is asize_t."
If you use the wrong label, printf() may read the bytes incorrectly or the compiler may warn you.
So the rule is simple:
- If the variable is
size_t, use%zu
Match the format to the real type, not to what you guess the type probably is on your machine.
Syntax and Examples
The correct portable syntax is:
#include <stdio.h>
#include <stddef.h>
size_t n = 42;
printf("%zu\n", n);
Example 1: Printing the result of sizeof
#include <stdio.h>
int main(void) {
printf("int uses %zu bytes\n", sizeof(int));
return 0;
}
sizeof(int) returns a size_t, so %zu is the correct format specifier.
Example 2: Printing an array length
#include <stdio.h>
int main() {
values[] = {, , , };
count = (values) / (values[]);
(, count);
;
}
Step by Step Execution
Consider this example:
#include <stdio.h>
int main(void) {
size_t count = sizeof(double) * 4;
printf("count = %zu\n", count);
return 0;
}
Step by step
-
sizeof(double)is evaluated.- Suppose
doubleis 8 bytes on your system.
- Suppose
-
sizeof(double) * 4becomes8 * 4.- The result is
32.
- The result is
-
That result is stored in
count.counthas typesize_t.
-
printf("count = %zu\n", count);is called.
Real World Use Cases
size_t appears often in real C programs, especially where code deals with memory, lengths, or buffer sizes.
Common situations
- Printing the result of
sizeof() - Displaying array lengths
- Showing buffer capacities
- Logging memory allocation sizes
- Reporting bytes read or written
- Working with string or data processing loops
Example: buffer logging
#include <stdio.h>
void log_buffer_size(size_t size) {
printf("Allocated buffer: %zu bytes\n", size);
}
Example: loop count reporting
#include <stdio.h>
int main(void) {
char text[] = "hello";
size_t len = sizeof(text) - 1;
printf("Text length: %zu\n", len);
return ;
}
Real Codebase Usage
In real projects, developers usually follow a few simple patterns when working with size_t.
1. Use size_t for sizes and counts
If a variable stores:
- number of elements
- buffer length
- byte count
- result of
sizeof
then size_t is usually the right type.
size_t capacity = 256;
size_t item_count = 10;
2. Print it with %zu
printf("capacity=%zu, item_count=%zu\n", capacity, item_count);
3. Validate sizes before allocation
if (count == 0) {
printf("No items to allocate\n");
return;
}
4. Use size_t consistently across APIs
{
( i = ; i < count; i++) {
(, i, items[i]);
}
}
Common Mistakes
Here are some frequent mistakes beginners make when printing size_t.
Mistake 1: Using %u
size_t n = 10;
printf("%u\n", n); // Wrong on some systems
Why it is a problem
%u expects unsigned int, but size_t may be a different type.
Fix
printf("%zu\n", n);
Mistake 2: Using %lu because it works on one machine
size_t n = 10;
printf("%lu\n", n); // Still not fully portable
Why it is a problem
This assumes size_t is unsigned long, which is not guaranteed everywhere.
Comparisons
Here is a quick comparison of common integer format choices when printing unsigned values in C.
| Format | Expected type | Good for size_t? | Notes |
|---|---|---|---|
%u | unsigned int | No | Only correct if the value is actually unsigned int |
%lu | unsigned long | No | Works only if size_t is unsigned long on that platform |
%zu | size_t | Yes | Portable standard choice |
Cheat Sheet
// Correct way to print size_t
size_t n = 42;
printf("%zu\n", n);
Rules
size_tis used for sizes, lengths, and countssizeof(...)returnssize_t- Use
%zuwithprintf()forsize_t - Do not assume
size_tisunsigned intorunsigned long
Common examples
printf("%zu\n", sizeof(int));
printf("length = %zu\n", len);
printf("capacity = %zu bytes\n", capacity);
Avoid
printf("%u\n", n); // not portable
(, n);
FAQ
What is the correct printf specifier for size_t in C?
Use %zu.
Why does %u sometimes work for size_t?
It works only on systems where size_t happens to be the same type as unsigned int. That is not guaranteed by the language.
Can I use %lu for size_t?
Only if size_t is actually unsigned long on that platform. For portable code, use %zu instead.
Does sizeof return int?
No. sizeof returns a value of type size_t.
Why does the compiler warn about %u with size_t?
Because expects an for , but your argument has type , which may be a different type.
Mini Project
Description
Build a small C program that reports the sizes of several data types and array lengths using size_t. This project demonstrates how size_t appears naturally in everyday C code and how to print it correctly with printf in a portable way.
Goal
Create a program that computes and prints several size-related values using %zu correctly.
Requirements
- Print the result of
sizeof(char),sizeof(int), andsizeof(double) - Store an array length in a
size_tvariable and print it - Use
%zufor everysize_tvalue - Include at least one loop that uses a
size_tindex
Keep learning
Related questions
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.
C Pointer to Array vs Array of Pointers: How to Read Complex Declarations
Learn the difference between pointer-to-array and array-of-pointers in C, plus a simple rule for reading complex declarations correctly.