Low-Level Byte Manipulation Functions in string.h
While the C standard library header string.h is commonly
associated with null-terminated character strings, it also provides the
primary standard tools for low-level byte manipulation. These functions
operate on raw memory blocks via void pointers, ignoring
null terminators and relying strictly on explicit byte counts. This
article outlines the essential low-level memory functions defined in
string.h—specifically memcpy,
memmove, memset, memcmp, and
memchr—detailing their purpose, syntax, and operational
mechanics.
memcpy
void *memcpy(void *dest, const void *src, size_t n);memcpy copies n consecutive bytes from the
memory area pointed to by src to the memory area pointed to
by dest. It does not check for terminating null bytes,
making it suitable for any data type, including binary structures and
primitive arrays.
- Behavior: Fastest standard memory-copy routine.
- Caveat: The source and destination memory blocks must not overlap. If they do, the behavior is undefined.
memmove
void *memmove(void *dest, const void *src, size_t n);Like memcpy, memmove copies n
bytes from src to dest. However,
memmove is explicitly designed to handle overlapping memory
blocks safely.
- Behavior: It behaves as though the bytes are first
copied to a temporary array that does not overlap
srcordest, and then written todest. - Use Case: Shifting elements within the same array or buffer.
memset
void *memset(void *s, int c, size_t n);memset fills the first n bytes of the
memory area pointed to by s with the constant byte
c (converted to an unsigned char).
- Behavior: Operates strictly on a byte-by-byte basis.
- Use Case: Commonly used to zero-initialize structs,
buffers, or arrays (
memset(ptr, 0, sizeof(*ptr))). It cannot be used to set multi-byte integers to arbitrary non-zero values (e.g., setting an array ofintto1results in each byte being0x01, producing0x01010101).
memcmp
int memcmp(const void *s1, const void *s2, size_t n);memcmp compares the first n bytes of two
memory blocks, s1 and s2, interpreting each
byte as an unsigned char.
- Return Value:
0if allnbytes are identical.- A negative value if the first differing byte in
s1is smaller than ins2. - A positive value if the first differing byte in
s1is greater than ins2.
- Caveat: Comparing struct instances with
memcmpmay yield unexpected results due to uninitialized padding bytes inserted by the compiler.
memchr
void *memchr(const void *s, int c, size_t n);memchr scans the initial n bytes of the
memory block pointed to by s for the first instance of the
byte c (converted to an unsigned char).
- Return Value: A pointer to the matching byte within
the block, or
NULLif the byte is not found within the specifiednbytes. - Use Case: Locating specific byte patterns or delimiters within raw binary data where strings are not null-terminated.
Core Differences from String Functions
- No Delimiter Dependency: Standard string functions
(like
strcpyorstrcmp) read memory until encountering a\0byte. Low-levelmem*functions ignore delimiters and process exactlynbytes, avoiding buffer overruns on non-string data. - Type Agnosticism: By utilizing
void *, these functions operate on arbitrary memory representations without requiring explicit type casting.