Search code examples
cmemcpy

Is it safe to use memcpy to insert an element in an array which has greater allocated size?


I have an array which contains a preallocated memory size for say 1000 elements. There is a counter to track the actual number of elements.

Is it safe to use memcpy to insert an alement at a given position?

If I run this, I see that it works, but I am in doubt about if it works by mere chance or it is fundamentally wrong approach as memcpy can not guarantee that the previous data is going to be preserved.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int *list;
    int list_size;
    
    // PREALLOCATE SPACE FOR 1000 ITEMS
    list = calloc(sizeof(int), 1000);
    list_size = 0;
    
    // ADD ITEMS
    list[0] = 2; list_size++;
    list[1] = 4; list_size++;
    list[2] = 6; list_size++;
    list[3] = 8; list_size++;
    list[4] = 10; list_size++;
    
    // LIST ITEMS
    printf("---\n"); for(int i=0; i<list_size; i++) printf("%04d\n", list[i]);
    
    // WE WANT TO INSERT A NUMBER AT A GIVEN POSITION (IN THIS CASE WE HAVE A POINTER TO THE ITEM)
    int *p = &list[3];
    
    // WE WANT TO PUSH FORWARD ALL THE ELEMENTS OF THE ARRAY BEFORE INSERTING THE ELEMENT
    memcpy( p+1, p, (list_size - (p - list))*sizeof(int));
    list_size++;
    
    // INSERT ELEMENT
    *p = -1;
    
    // LIST ITEMS
    printf("---\n"); for(int i=0; i<list_size; i++) printf("%04d\n", list[i]);
    
    return 0;
}

The output:

---
0002
0004
0006
0008
0010
---
0002
0004
0006
-001
0008
0010

Solution

  • memcpy has undefined behavior in case the two parameters point to memory that overlaps. You need to use memmove instead, it exists for this very purpose.

    See the friendly manual or the C standard 7.24.1:

    The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined.

    The memmove function copies n characters from the object pointed to by s2 into the object pointed to by s1. Copying takes place as if the n characters from the object pointed to by s2 are first copied into a temporary array of n characters that does not overlap the objects pointed to by s1 and s2, and then the n characters from the temporary array are copied into the object pointed to by s1.