Question
I want to print an int64_t value in C without compiler warnings and in a portable way.
I currently have code like this:
#include <stdio.h>
#include <stdint.h>
int main(void) {
int64_t my_int = 999999999999999999;
printf("This is my_int: %I64d\n", my_int);
return 0;
}
On some systems, I also tried:
printf("This is my_int: %lld\n", my_int);
but I still get a warning that the format specifier does not match the type of my_int.
I am compiling with GCC 4.2.1 on an Apple system.
Which format specifier should be used to print an int64_t value correctly and portably in C, without warnings?
Short Answer
By the end of this page, you will understand why int64_t should not be printed with hard-coded format specifiers like %lld or %I64d, and how to print it portably using the macros from inttypes.h, such as PRId64 and PRIu64. You will also see how this fits into real C codebases and how to avoid common printf format mismatches.
Concept
In C, fixed-width integer types such as int64_t and uint64_t are defined in stdint.h. They guarantee a width, such as exactly 64 bits, but they do not guarantee which base C type is used underneath.
For example, on one platform int64_t might be a long, while on another it might be a long long. Because printf requires the format string to match the actual underlying type, using a hard-coded specifier like %lld or %I64d is not fully portable.
That is why C provides inttypes.h. This header defines format macros specifically for fixed-width integer types:
PRId64for signedint64_tPRIu64for unsigneduint64_t- and many others for other integer widths
These macros expand to the correct format string for the current platform.
This matters because printf is a variadic function. Variadic functions do not know argument types automatically. They trust the format string. If the format string and argument type do not match, you can get:
Mental Model
Think of int64_t as a box labeled "64-bit signed integer".
The label tells you the size of the value, but not the exact material the box is made from. On one machine, the box might really be a long; on another, a long long.
printf does not look at the label on the box. It only follows the instructions in the format string.
So if you say %lld, you are telling printf: "Expect a long long."
If the value is actually represented as a long on that platform, the instruction does not match the box.
PRId64 is like asking the compiler: "Please give me the right instruction for this platform."
Syntax and Examples
To print fixed-width integers portably, include both stdint.h and inttypes.h.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
Signed int64_t
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(void) {
int64_t my_int = 999999999999999999;
printf("This is my_int: %" PRId64 "\n", my_int);
return 0;
}
Unsigned uint64_t
#include
{
value = ;
( PRIu64 , value);
;
}
Step by Step Execution
Consider this example:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(void) {
int64_t count = 42;
printf("count = %" PRId64 "\n", count);
return 0;
}
Here is what happens step by step:
#include <stdint.h>defines the typeint64_t.#include <inttypes.h>defines the macroPRId64.int64_t count = 42;stores a 64-bit signed integer.- The compiler sees:
"count = %" PRId64 "\n" - It expands
PRId64to the correct platform-specific format part, such aslldorld.
Real World Use Cases
Portable fixed-width integer printing is common in real programs where exact integer sizes matter.
File sizes and byte counters
uint64_t bytes_processed = 1234567890ULL;
printf("Processed %" PRIu64 " bytes\n", bytes_processed);
Timestamps and IDs
int64_t event_id = 91234567890123;
printf("Event ID: %" PRId64 "\n", event_id);
Cross-platform libraries
If your code runs on Linux, macOS, and Windows, you should avoid platform-specific specifiers like %I64d.
Binary protocols and data formats
When reading or writing 64-bit values from network packets, database files, or custom binary formats, developers often use int64_t and uint64_t. Printing them correctly is important for debugging and logging.
Real Codebase Usage
In real C projects, developers usually follow these patterns:
Logging fixed-width values
fprintf(stderr, "offset=%" PRId64 "\n", offset);
This keeps logs portable across compilers and operating systems.
Validation and diagnostics
if (size < 0) {
fprintf(stderr, "Invalid size: %" PRId64 "\n", size);
return 1;
}
Configuration and parsing tools
Programs that parse configuration files or command-line arguments often store results in fixed-width types and print them back for debugging.
Wrapping format details in macros or helpers
Large codebases sometimes create helper functions for repeated logging:
void print_record_id(int64_t id) {
printf("record id=%" PRId64 "\n", id);
}
This reduces repeated format mistakes.
Error handling
When printing values during failures, using the correct format matters even more because debugging output must be trustworthy.
Common Mistakes
Mistake 1: Using %lld for every int64_t
int64_t x = 10;
printf("%lld\n", x); // may warn on some systems
Why it is a problem:
int64_tis not guaranteed to belong long- it may be
longon some platforms
Use this instead:
printf("%" PRId64 "\n", x);
Mistake 2: Using Windows-specific %I64d
printf("%I64d\n", x);
Why it is a problem:
%I64dis not standard C portable syntax- it may fail or warn on non-Windows compilers
Use PRId64 instead.
Mistake 3: Forgetting to include
Comparisons
| Approach | Example | Portable? | Notes |
|---|---|---|---|
| Platform-specific specifier | %I64d | No | Common on older Windows compilers |
Hard-coded long long specifier | %lld | Sometimes | Works only if int64_t is actually long long |
Hard-coded long specifier | %ld | Sometimes | Works only if int64_t is actually long |
inttypes.h macro |
Cheat Sheet
#include <stdint.h>
#include <inttypes.h>
Print fixed-width integers
int64_t a;
uint64_t b;
printf("%" PRId64 "\n", a);
printf("%" PRIu64 "\n", b);
Common macros
| Type | Decimal macro |
|---|---|
int8_t | PRId8 |
int16_t | PRId16 |
int32_t | PRId32 |
FAQ
What is the correct portable way to print int64_t in C?
Use PRId64 from inttypes.h:
printf("%" PRId64 "\n", value);
Why does %lld sometimes produce a warning for int64_t?
Because int64_t is not guaranteed to be long long on every platform. It may be a different underlying type.
Do I need both stdint.h and inttypes.h?
Yes. stdint.h gives you int64_t, and inttypes.h gives you PRId64.
Can I use %I64d in portable C code?
No. %I64d is compiler- or platform-specific and should not be used for portable code.
How do I print ?
Mini Project
Description
Build a small command-line program that prints several fixed-width integer values in a portable way. This project demonstrates how to combine stdint.h types with inttypes.h format macros for clean, warning-free output across platforms.
Goal
Create a C program that prints signed and unsigned fixed-width integers using the correct portable printf macros.
Requirements
- Include
stdint.h,inttypes.h, andstdio.h - Declare at least one
int64_tand oneuint64_tvariable - Print both values using the correct format macros
- Add one additional fixed-width integer type such as
int32_toruint32_t - Ensure the program uses portable format strings only
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.