<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.
Fundamentals
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.
Foundation
📝 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.
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+).
Cheat Sheet
⚡ Quick Reference
Symbol
Kind
Purpose
size_t
typedef
Unsigned sizes and counts
ptrdiff_t
typedef
Signed pointer difference
NULL
macro
Null pointer constant
offsetof(T, m)
macro
Byte offset of member m
wchar_t
typedef
Wide character type
%zu
format
Print 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
Hands-On
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;
}
📤 Output (typical 64-bit GCC):
Size of Employee: 64 bytes
Offset of salary: 56 bytes
sizeof(int)=4, sizeof(double)=8
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.”
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;
}
📤 Output:
Elements between start and end: 4
Byte distance (char*): 16
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;
}
📤 Output:
Count: 4, Sum: 355, Average: 88.8
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.
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.
Array bounds — loop with size_t up to element count.
Optional pointers — use NULL for “not set” or end-of-list sentinels.
Binary protocols — offsetof documents field layout in structs.
Iterator distance — ptrdiff_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.
Important
📝 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.
Performance
⚡ 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.
Wrap Up
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.
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
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about stddef.h
Sizes, pointers, and layout in one header.
5
Core concepts
💬01
size_t
Unsigned size.
Type
📚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.