C Standard Library stddef.h

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
<stddef.h>

What You’ll Learn

<stddef.h> is one of the smallest but most important C headers. It defines types and macros for sizes, pointer differences, null pointers, and structure layout—building blocks used by malloc, strlen, arrays, and almost every library function that deals with memory.

01

size_t

Unsigned size.

02

ptrdiff_t

Pointer diff.

03

NULL

Null pointer.

04

offsetof

Member offset.

05

wchar_t

Wide char.

06

%zu

Print size_t.

Definition and Usage

stddef.h provides portable names for concepts the compiler already understands: how big something is (size_t), how far apart two pointers are (ptrdiff_t), what “no object” means for a pointer (NULL), and where a field sits inside a struct (offsetof).

You rarely call functions from this header. Instead, you use its types and macros everywhere—especially with sizeof, dynamic memory, string lengths, and pointer arithmetic.

💡
Beginner Tip

Other headers like <stdio.h> and <stdlib.h> pull in stddef.h for you. Still, include <stddef.h> directly when your file only needs size_t, NULL, or offsetof—it documents intent and keeps dependencies minimal.

📝 Syntax

Include the header:

C
#include <stddef.h>

Types and macros defined in stddef.h

  • size_t — unsigned integer type; result of sizeof and sizes for malloc, strlen, etc.
  • ptrdiff_t — signed integer type; result of subtracting two pointers to the same array.
  • wchar_t — integer type for wide characters (see also <wchar.h>).
  • NULL — null pointer constant macro.
  • offsetof(type, member) — byte offset of member within type.
  • max_align_t — (C11) type with maximum alignment requirement.

Typical forms (implementation-defined details)

C
typedef /* implementation-defined */ size_t;
typedef /* implementation-defined */ ptrdiff_t;
typedef /* implementation-defined */ wchar_t;

#define NULL /* null pointer constant, often ((void *)0) or 0 */

#define offsetof(type, member) /* byte offset */

Common usage

C
size_t n = sizeof(int);
char *p = NULL;

if (p == NULL) {
    /* no valid object */
}

ptrdiff_t gap = &arr[5] - &arr[0];   /* same array only */

size_t off = offsetof(struct S, field);

Headers and linking

  • #include <stddef.h> — types and macros only; no extra link flag.
  • Print size_t with %zu in printf (C99+).
  • Print ptrdiff_t with %td (C99+).

⚡ Quick Reference

SymbolKindPurpose
size_ttypedefUnsigned sizes and counts
ptrdiff_ttypedefSigned pointer difference
NULLmacroNull pointer constant
offsetof(T, m)macroByte offset of member m
wchar_ttypedefWide character type
%zuformatPrint size_t
Size
size_t n = sizeof(x);

Store sizeof

Null
if (p == NULL)

Check pointer

Offset
offsetof(S, f)

Struct layout

Diff
p - q

ptrdiff_t result

Examples Gallery

Compile with gcc file.c -std=c11 -o out. Structure sizes and offsets in Example 1 depend on platform alignment; output shown is typical on 64-bit GCC.

📚 Getting Started

Core types from the reference, expanded with clear output.

Example 1 — sizeof with size_t and offsetof

From the reference: measure a structure and find where salary sits in memory.

C
#include <stdio.h>
#include <stddef.h>

typedef struct {
    int id;
    char name[50];
    double salary;
} Employee;

int main(void) {
    Employee emp = { 1, "John Doe", 75000.0 };
    size_t total = sizeof(Employee);
    size_t off = offsetof(Employee, salary);

    (void)emp;
    printf("Size of Employee: %zu bytes\n", total);
    printf("Offset of salary: %zu bytes\n", off);
    printf("sizeof(int)=%zu, sizeof(double)=%zu\n",
           sizeof(int), sizeof(double));

    return 0;
}

How It Works

sizeof returns size_t. The compiler may insert padding between members so double is aligned—that is why the offset of salary is not simply 4 + 50. Always use %zu to print size_t, not %d or %u.

Example 2 — NULL Pointer Check

Always test pointers before dereferencing. NULL means “points nowhere.”

C
#include <stdio.h>
#include <stddef.h>

void greet(const char *name) {
    if (name == NULL) {
        printf("No name provided.\n");
        return;
    }
    printf("Hello, %s!\n", name);
}

int main(void) {
    greet("Ada");
    greet(NULL);
    return 0;
}

How It Works

NULL compares equal to any null pointer. if (!name) is equivalent to if (name == NULL) for pointers. Never assign NULL to an int or other non-pointer type.

📈 Practical Patterns

Pointer arithmetic, loops, and wide characters.

Example 3 — ptrdiff_t from Pointer Subtraction

Subtracting two pointers to the same array yields element count, stored as ptrdiff_t.

C
#include <stdio.h>
#include <stddef.h>

int main(void) {
    int data[] = { 10, 20, 30, 40, 50 };
    int *start = &data[0];
    int *end = &data[4];

    ptrdiff_t count = end - start;
    ptrdiff_t bytes = (char *)end - (char *)start;

    printf("Elements between start and end: %td\n", count);
    printf("Byte distance (char*): %td\n", bytes);

    return 0;
}

How It Works

end - start counts int elements (4), not bytes. Casting to char * before subtracting gives byte distance (16 on typical 4-byte int). Only subtract pointers into the same array object (or one past the end).

Example 4 — size_t for Array Indexing

Use size_t when looping up to sizeof(array)/sizeof(array[0]).

C
#include <stdio.h>
#include <stddef.h>

int main(void) {
    int scores[] = { 88, 92, 75, 100 };
    size_t i;
    size_t n = sizeof(scores) / sizeof(scores[0]);
    size_t sum = 0;

    for (i = 0; i < n; i++) {
        sum += (size_t)scores[i];
    }

    printf("Count: %zu, Sum: %zu, Average: %.1f\n",
           n, sum, (double)sum / (double)n);

    return 0;
}

How It Works

sizeof(scores)/sizeof(scores[0]) is a common idiom for element count. The loop index i is size_t so it matches n without signed/unsigned warnings. Watch out: comparing a signed int to size_t can surprise you when the signed value is negative.

Example 5 — wchar_t Size (Wide Characters)

stddef.h defines wchar_t; wide literals use the L prefix.

C
#include <stdio.h>
#include <stddef.h>

int main(void) {
    wchar_t letter = L'A';
    char narrow = 'A';

    printf("sizeof(char)   = %zu\n", sizeof(char));
    printf("sizeof(wchar_t)= %zu\n", sizeof(wchar_t));
    printf("narrow value: %d\n", (int)narrow);
    printf("wide value:   %d\n", (int)letter);

    return 0;
}

How It Works

wchar_t width varies by platform (often 2 bytes on Windows, 4 on Linux). For Unicode text in modern C, many projects use char with UTF-8 instead. Use <wchar.h> when you need wide string functions.

🚀 Common Use Cases

  • Dynamic memorymalloc(n * sizeof(T)) returns void *; size argument is size_t.
  • String lengthsstrlen returns size_t.
  • Array bounds — loop with size_t up to element count.
  • Optional pointers — use NULL for “not set” or end-of-list sentinels.
  • Binary protocolsoffsetof documents field layout in structs.
  • Iterator distanceptrdiff_t for pointer subtraction in buffers.

🧠 How stddef.h Fits In

1

Compiler knows sizes

sizeof and pointer math produce implementation-specific values.

Types
2

stddef.h names them

size_t, ptrdiff_t, NULL give portable spellings.

Portability
3

Other headers reuse them

stdio, stdlib, string build on the same types.

Ecosystem
=

Consistent memory code

One vocabulary for sizes, null pointers, and layout across your program.

📝 Notes

  • size_t is unsigned—avoid comparing it to negative signed values without casting.
  • Subtract pointers only within the same array object (C rule).
  • offsetof on bit-fields is undefined; use only on normal members.
  • Structure padding makes offsets platform-specific; do not hard-code magic numbers.
  • NULL expands to an implementation-defined null pointer constant—commonly 0 or ((void *)0).
  • C11 adds max_align_t to stddef.h for alignment queries.

⚡ Optimization

size_t and ptrdiff_t are typedefs—no runtime cost. offsetof is resolved at compile time. Choosing size_t for indices matching strlen or malloc sizes avoids extra casts and warnings. For micro-optimization of struct layout, reorder members to reduce padding, but prefer clarity unless profiling shows memory pressure.

Conclusion

<stddef.h> is the foundation for talking about sizes and pointers in portable C. Use size_t with sizeof and memory functions, NULL for empty pointers, ptrdiff_t for pointer gaps, and offsetof when layout matters.

You will see these names in almost every C program. Learning them early makes malloc, strings, and arrays much easier to read.

💡 Best Practices

✅ Do

  • Use %zu for size_t in printf
  • Check pointers against NULL before use
  • Use size_t for sizes from sizeof / strlen
  • Use offsetof instead of hard-coded byte offsets
  • Include <stddef.h> when you need only these basics

❌ Don’t

  • Assign NULL to non-pointer variables
  • Subtract unrelated pointers (undefined behavior)
  • Print size_t with %d (wrong on many platforms)
  • Assume struct layout is identical on every OS
  • Apply offsetof to bit-field members

Key Takeaways

Knowledge Unlocked

Five things to remember about stddef.h

Sizes, pointers, and layout in one header.

5
Core concepts
📚 02

NULL

No object.

Macro
📈 03

offsetof

Field byte.

Layout
📄 04

ptrdiff_t

p - q.

Signed
🌐 05

%zu

Print size.

Format

❓ Frequently Asked Questions

stddef.h is a core C standard header that defines fundamental types and macros used across the library: size_t for sizes, ptrdiff_t for pointer differences, wchar_t for wide characters, NULL for null pointers, and offsetof for structure member offsets. Many other headers include it indirectly.
size_t is unsigned and holds the result of sizeof and sizes passed to malloc. ptrdiff_t is signed and holds the difference between two pointers to the same array (p - q). Use size_t for counts and sizes; use ptrdiff_t when subtracting pointers.
NULL is a macro for a null pointer constant. It represents a pointer that does not point to any object. Compare with if (ptr == NULL) or if (!ptr) before dereferencing. Do not use NULL for non-pointer types.
offsetof(type, member) expands to the byte offset of member within a structure or union of type. It is useful for serialization, binary layouts, and low-level code. Do not apply offsetof to bit-fields; that is undefined behavior.
Often no—stdio.h, stdlib.h, string.h, and others include stddef.h or define size_t. For portable, minimal code that only needs size_t or NULL, #include <stddef.h> explicitly is clearest.
No. char is for narrow characters (typically 1 byte). wchar_t is an integer type for wide characters (often 2 or 4 bytes). Wide string literals use L"text". See wchar.h for wide-character functions; stddef.h only declares the type.
Did you know?

The C standard requires that size_t be large enough to represent the size of any single object. On a 64-bit system that often means 64 bits unsigned—so storing a negative value in a size_t wraps to a huge positive number, which is a common source of subtle bugs in loops.

Explore C Standard Library Headers

Continue with stdint.h or browse the library index.

Standard Library Index →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful