C memmove function
last modified April 8, 2025
Memory operations are fundamental in C programming, and memmove
is a
safe function for copying data between memory locations. This tutorial covers
memmove
in depth, including its syntax, usage, and advantages over
memcpy
. We'll explore practical examples showing how it handles
overlapping memory regions safely. Understanding memmove
helps write
robust programs that avoid undefined behavior in memory operations.
What Is memmove?
The memmove
function copies a block of memory from one location to
another safely. It's declared in string.h
and takes three parameters:
destination pointer, source pointer, and number of bytes to copy.
memmove
handles overlapping memory regions correctly by checking
memory ranges before copying. Unlike memcpy
, it guarantees correct
behavior even when source and destination buffers overlap.
Basic memmove Usage
This example demonstrates copying data between two arrays using
memmove
.
#include <stdio.h> #include <string.h> int main() { char src[] = "Hello, World!"; char dest[20]; // Copy 14 bytes (including null terminator) memmove(dest, src, 14); printf("Source: %s\n", src); printf("Destination: %s\n", dest); return 0; }
Here, memmove
copies 14 bytes from src
to
dest
, including the null terminator. The function behaves like
memcpy
when buffers don't overlap. The destination buffer must be
large enough to hold the copied data. This is the safe way to copy memory when
you're unsure about potential overlaps.
Handling Overlapping Memory Regions
This example demonstrates memmove
's ability to handle overlapping
regions correctly.
#include <stdio.h> #include <string.h> int main() { char data[] = "ABCDEFGHIJ"; // Move data within the same buffer (overlapping) memmove(data + 2, data, 5); printf("Result: %s\n", data); return 0; }
This code safely copies data even though source and destination overlap.
memmove
checks memory ranges and copies in the correct direction to
preserve data integrity. The output will be "ABABCDEFIJ" because the first 5
bytes are copied starting at position 2. This behavior is guaranteed and
portable across platforms.
Moving Array Elements
This example shows how to shift elements within an array using
memmove
.
#include <stdio.h> #include <string.h> int main() { int nums[] = {1, 2, 3, 4, 5, 6, 7, 8}; size_t count = sizeof(nums)/sizeof(nums[0]); // Shift elements left by 2 positions memmove(nums, nums + 2, (count - 2) * sizeof(int)); printf("Shifted array: "); for (size_t i = 0; i < count - 2; i++) { printf("%d ", nums[i]); } printf("\n"); return 0; }
Here, memmove
shifts array elements left by two positions. The
function correctly handles the overlapping source and destination regions. The
size calculation uses (count - 2) * sizeof(int)
to get the correct
byte count. After the move, the array contains {3,4,5,6,7,8} in its first six
positions.
Copying Structures with memmove
memmove
can safely copy structures, even when they might overlap.
#include <stdio.h> #include <string.h> typedef struct { int id; char name[20]; float score; } Student; int main() { Student students[3] = { {101, "Alice", 95.5}, {102, "Bob", 88.0}, {103, "Charlie", 91.2} }; // Move second student to first position memmove(&students[0], &students[1], sizeof(Student)); printf("First student is now: %s\n", students[0].name); return 0; }
This example moves a Student
structure within an array using
memmove
. The sizeof(Student)
ensures we copy the exact
number of bytes needed. Since the source and destination are in the same array,
memmove
is the correct choice. After execution, the first array
element contains Bob's data.
Implementing a Circular Buffer
This example demonstrates using memmove
in a circular buffer
implementation.
#include <stdio.h> #include <string.h> #define BUF_SIZE 16 void add_to_buffer(char *buf, size_t *count, char data) { if (*count == BUF_SIZE) { // Make room by shifting left memmove(buf, buf + 1, BUF_SIZE - 1); (*count)--; } buf[(*count)++] = data; } int main() { char buffer[BUF_SIZE] = {0}; size_t count = 0; // Fill the buffer for (char c = 'A'; c < 'Q'; c++) { add_to_buffer(buffer, &count, c); } // Add one more, causing a shift add_to_buffer(buffer, &count, 'Q'); printf("Buffer: %.*s\n", (int)count, buffer); return 0; }
This code implements a simple circular buffer using memmove
to shift
elements when the buffer is full. The function maintains the most recent
BUF_SIZE
characters. When adding 'Q', it shifts all characters left
to make room. The output shows "BCDEFGHIJKLMNOPQ" - the first 'A' was dropped
to maintain buffer size.
Best Practices for Using memmove
- Prefer over memcpy: Use
memmove
when unsure about memory overlap. - Check buffer sizes: Ensure destination has enough space for the moved data.
- Use correct size: Calculate byte counts carefully with
sizeof
. - Verify pointers: Ensure both source and destination pointers are valid.
- Consider performance:
memmove
may be slightly slower thanmemcpy
.
Source
This tutorial has explored the memmove
function, from basic usage to
advanced memory operations. Its ability to handle overlapping regions makes it
safer than memcpy
for many use cases. Always consider memory safety
when working with low-level operations in C.
Author
List C Standard Library.