Question
In C, printf uses conversion specifiers such as %d or %i to print a signed int. What conversion specifier should be used to print a long value correctly?
Short Answer
By the end of this page, you will understand how printf formats long values in C, why the correct conversion specifier matters, how length modifiers work, and how to avoid common type-mismatch bugs when printing integers.
Concept
printf in C does not guess argument types at runtime. It relies entirely on the format string you provide.
For integer output, the base conversion specifier for a signed decimal integer is %d or %i. To print other integer types, C uses length modifiers that are placed before the conversion letter.
For a long, the correct signed decimal format is:
%ld
You can also use:
%li
Both are valid for printf when printing a signed long, though %ld is more commonly used.
For an unsigned long, use:
%lu
This matters because printf is a variadic function. Variadic functions do not know the actual types of extra arguments unless the format string describes them correctly. If you pass a long but use %d, printf will interpret the bytes as if they were an int, which can produce incorrect output and causes undefined behavior.
In real programs, this becomes especially important when:
- printing counters n- working with file sizes or timestamps
- logging numeric values
- handling platform-dependent integer sizes
Using the correct format keeps your output accurate and your code portable.
Mental Model
Think of printf like a labeling machine in a warehouse.
- The value is the package.
- The format specifier is the label telling the machine what kind of package it is.
If you put a long package on the belt but label it as %d (an int), the machine reads it using the wrong instructions. Sometimes the output looks almost right, sometimes it is completely wrong, and sometimes it causes subtle bugs.
%ld means: “This is a signed decimal number, and its type is long.”
Syntax and Examples
The general syntax is:
printf("format string", value);
For long, use %ld:
#include <stdio.h>
int main(void) {
long distance = 1234567890L;
printf("Distance: %ld\n", distance);
return 0;
}
Output:
Distance: 1234567890
For unsigned long, use %lu:
#include <stdio.h>
int main(void) {
unsigned long population = 4000000000UL;
printf("Population: %lu\n", population);
return 0;
}
For other common integer types:
int a = 10;
long b = 20L;
long long c = 30LL;
printf("int: %d\n", a);
printf("long: %ld\n", b);
printf("long long: %lld\n", c);
A broken example:
long value = 1234567890L;
printf("%d\n", value); // Wrong
Correct version:
printf("%ld\n", value); // Correct
Even if the wrong version appears to work on one machine, it is still incorrect C.
Step by Step Execution
Consider this example:
#include <stdio.h>
int main(void) {
long score = 500000L;
printf("Score = %ld\n", score);
return 0;
}
Step by step:
-
long score = 500000L;- A variable named
scoreis created. - Its type is
long. - The
Lsuffix makes the literal alongconstant.
- A variable named
-
printf("Score = %ld\n", score);printfreads the format string.- It finds
%ld. %lmeans the argument is along.dmeans print it as a signed decimal integer.printfreadsscoreas alongand prints500000.
-
\n- Moves output to the next line.
-
return 0;- Ends the program successfully.
If the code had used %d instead of %ld, printf would expect an int, not a long. That mismatch leads to undefined behavior.
Real World Use Cases
Printing long values appears in many practical situations:
-
Counters and IDs
- Large loop counters
- Record IDs stored in
long
-
Timestamps
- Unix-style time values are often stored in larger integer types
-
File sizes and offsets
- Programs may use
longor related integer types for file positions
- Programs may use
-
System logs
- Logging process data, durations, counts, or totals
-
Scientific and numeric programs
- Intermediate results may exceed the range of
int
- Intermediate results may exceed the range of
Example:
long total_requests = 1250000L;
printf("Processed requests: %ld\n", total_requests);
In each case, the format string must match the actual variable type.
Real Codebase Usage
In real codebases, developers usually combine correct format specifiers with a few common patterns:
Validation and logging
if (count < 0) {
printf("Invalid count: %ld\n", count);
return 1;
}
This is a simple example of a guard clause: detect a bad value early, log it, and stop.
Debug output
long retries = 3L;
printf("Retry attempt: %ld\n", retries);
Developers often print numeric state while debugging.
Configuration values
long timeout_ms = 5000L;
printf("Timeout set to %ld ms\n", timeout_ms);
Configuration values are often read, validated, and then logged.
Matching type and format consistently
Teams usually try to keep these aligned:
- variable type:
long - literal suffix:
Lwhen useful - format string:
%ld
That consistency makes code easier to review and less error-prone.
Compiler warnings as protection
Real projects often compile with warnings enabled, such as:
gcc -Wall -Wextra -Wformat program.c
These warnings help catch mistakes like using %d for a long.
Common Mistakes
1. Using %d for a long
Broken code:
long n = 100000L;
printf("%d\n", n);
Problem:
%dexpects anintnis along- This is undefined behavior
Fix:
printf("%ld\n", n);
2. Forgetting unsigned types need different specifiers
Broken code:
unsigned long n = 42UL;
printf("%ld\n", n);
Problem:
%ldis for signedlongnisunsigned long
Fix:
printf("%lu\n", n);
3. Confusing long with long long
Broken code:
long long big = 9000000000LL;
printf("%ld\n", big);
Fix:
printf("%lld\n", big);
4. Assuming sizes are the same on every platform
Some systems have:
int= 32 bitslong= 32 bits
Others may have:
int= 32 bitslong= 64 bits
Do not assume %d is “close enough.” Always match the actual type.
5. Ignoring compiler warnings
If the compiler says the format does not match the argument type, take it seriously. These warnings often catch real bugs early.
Comparisons
Here is a quick comparison of common integer format specifiers in C:
| Type | Signed format | Unsigned format | Example variable |
|---|---|---|---|
int | %d or %i | %u | int x = 10; |
long | %ld or %li | %lu | long x = 10L; |
long long | %lld | %llu | long long x = 10LL; |
short | %hd | %hu | short x = 10; |
%d vs %i
For printf, %d and %i behave the same for output.
%ld vs %li
For printf, both print a signed long.
%ld vs %lld
%ldis forlong%lldis forlong long
Choose the one that matches your variable exactly.
Cheat Sheet
- Print signed
long:%ld - Print unsigned
long:%lu - Print signed
int:%dor%i - Print signed
long long:%lld
Examples:
long a = 123L;
unsigned long b = 123UL;
long long c = 123LL;
printf("%ld\n", a);
printf("%lu\n", b);
printf("%lld\n", c);
Rules:
lis the length modifier forlongdandiare signed decimal output specifiers- The format string must match the argument type exactly
- Mismatched types in
printfcause undefined behavior
Useful reminders:
%ld= signedlong%lu= unsignedlong%lialso works for signedlonginprintf- Enable compiler warnings to catch mistakes
Compilation tip:
gcc -Wall -Wextra -Wformat program.c
FAQ
What is the correct printf specifier for a long in C?
Use %ld for a signed long.
Can I use %i for a long?
Not by itself. For a long, use %li or %ld. In printf, both are valid for signed decimal output.
What is the specifier for unsigned long?
Use %lu.
Why is %d wrong for a long?
Because %d expects an int. If you pass a long, the format and argument types do not match, which causes undefined behavior.
Is %ld the same as %li?
For printf, yes. Both print a signed long as decimal output.
What about long long?
Use %lld for signed long long and %llu for unsigned long long.
Will the wrong format always fail visibly?
No. Sometimes it may appear to work, but the code is still incorrect and non-portable.
Mini Project
Description
Build a small C program that prints several integer variables using the correct printf format specifiers. This reinforces how signed and unsigned integer types must match their format strings exactly.
Goal
Create a program that correctly prints int, long, unsigned long, and long long values.
Requirements
- Declare one variable of type
int. - Declare one variable of type
long. - Declare one variable of type
unsigned long. - Declare one variable of type
long long. - Print each variable using the correct
printfconversion specifier.
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.