C Mastery / inttypes.h and Extended Integer Types
Part 3 — The Standard Library

inttypes.h and Extended Integer Types

This chapter covers <inttypes.h>: the format macros for printing and scanning fixed-width integer types portably, plus the related intmax_t/uintmax_t.

Why This Matters

Fixed-width types (int32_t, uint64_t, etc.) have implementation-defined underlying types, so %d or %lld is not portable. <inttypes.h> provides the correct format specifiers, eliminating a whole class of portability bugs.

Prerequisites

Core Concept

<inttypes.h> includes <stdint.h> and defines macros that expand to the correct format specifier for each fixed-width type.

Printing

#include <inttypes.h>
#include <stdio.h>

int32_t  a = -5;
uint64_t b = 10000000000ULL;

printf("%" PRId32 "\n", a);   /* PRId32 expands to the right %...d */
printf("%" PRIu64 "\n", b);
printf("%" PRIx64 "\n", b);   /* hex */

The macros are string literals, so they must be concatenated with the format string using adjacent string literal concatenation ("%" PRId32).

Scanning

int32_t x;
scanf("%" SCNd32, &x);

SCNd32 is the scan counterpart.

Key Macros

FormatSignedUnsigned
decimalPRIdNPRIuN
octalPRIoNPRIoN
hexPRIxN/PRIXNPRIxN/PRIXN
scanSCNdN/SCNuN/SCNxNsame

Where N is 8, 16, 32, 64, LEASTN, FASTN, MAX, or PTR.

Examples

Portable printing of all widths

#include <stdio.h>
#include <inttypes.h>

int main(void)
{
    int8_t   a = -1;
    uint8_t  b = 255;
    int64_t  c = -9000000000000000000LL;
    uintmax_t d = UINTMAX_MAX;

    printf("%" PRId8 " %" PRIu8 "\n", a, b);
    printf("%" PRId64 "\n", c);
    printf("%" PRIuMAX "\n", d);
    return 0;
}

How It Works

The implementation defines each macro as the correct string for its platform's underlying types. For example, on LP64, PRId64 expands to "ld", while on LLP64 it expands to "lld". The macro hides this difference.

Variations

intmax_t/uintmax_t

intmax_t/uintmax_t are the largest supported integer types. Use them when you need "the widest available integer" and format with PRIdMAX/PRIuMAX.

intptr_t/uintptr_t

For storing pointers in integers, format with PRIdPTR/PRIuPTR.

Common Mistakes

Undefined Behavior

the underlying type is long long) is UB. <inttypes.h> macros prevent this.

Portability

fixed-width types.

Under the Hood

The macros are preprocessor string constants. They are resolved at compile time; there is no run-time cost.

Practical Usage

Exercises

1. Write a program that prints int8_t, uint64_t, and intptr_t values portably using the macros. 2. Demonstrate what happens (or what warning you get) if you use %d for a int64_t. 3. Use SCNd32 to read an int32_t.

Deep Challenge

Write a portable logging function that prints a uint64_t in hex with a fixed width and zero padding, using <inttypes.h> macros only. Explain why you cannot hard-code the width.

References

Verification

verified.`

Progress

Concept checkboxes

Mastery levels

ConceptCurrent level (0–8)Target level
c.lib.inttypes05