Namespaces
Variants

memmove, memmove_s

From cppreference.net
< c ‎ | string ‎ | byte
Definiert in Header <string.h>
void * memmove ( void * dest, const void * src, size_t count ) ;
(1)
errno_t memmove_s ( void * dest, rsize_t destsz, const void * src, rsize_t count ) ;
(2) (seit C11)
1) Kopiert count Zeichen vom Objekt, auf das src zeigt, zum Objekt, auf das dest zeigt. Beide Objekte werden als Arrays von unsigned char interpretiert. Die Objekte können sich überlappen: Das Kopieren erfolgt so, als ob die Zeichen in ein temporäres Zeichenarray kopiert würden und dann die Zeichen vom Array zu dest kopiert würden.
Das Verhalten ist undefiniert, wenn der Zugriff über das Ende des dest-Arrays hinaus erfolgt. Das Verhalten ist undefiniert, wenn entweder dest oder src ein ungültiger oder null-Zeiger ist.
2) Gleich wie (1) , außer dass bei Erkennung der folgenden Fehler zur Laufzeit der gesamte Zielbereich [ dest, dest + destsz ) auf Null gesetzt wird (sofern sowohl dest als auch destsz gültig sind) und die aktuell installierte Constraint-Handler-Funktion aufgerufen wird:
  • dest oder src ist ein Nullzeiger
  • destsz oder count ist größer als RSIZE_MAX
  • count ist größer als destsz (ein Pufferüberlauf würde auftreten)
Das Verhalten ist undefiniert, wenn die Größe des Zeichenarrays, auf das dest zeigt, < count <= destsz ; mit anderen Worten, ein fehlerhafter Wert von destsz macht den drohenden Pufferüberlauf nicht sichtbar.
Wie bei allen grenzprüfenden Funktionen ist memmove_s nur garantiert verfügbar, wenn __STDC_LIB_EXT1__ durch die Implementierung definiert ist und wenn der Benutzer __STDC_WANT_LIB_EXT1__ auf den ganzzahligen Konstantenwert 1 setzt, bevor <string.h> eingebunden wird.

Inhaltsverzeichnis

Parameter

dest - Zeiger auf das zu kopierende Zielobjekt
destsz - maximale Anzahl der Bytes, die im Ziel modifiziert werden sollen (typischerweise die Größe des Zielobjekts)
src - Zeiger auf das zu kopierende Quellobjekt
count - Anzahl der zu kopierenden Bytes

Rückgabewert

1) Gibt eine Kopie von dest zurück
2) Gibt bei Erfolg Null zurück und bei Fehler einen Nicht-Null-Wert. Bei Fehler wird, falls dest kein Nullzeiger ist und destsz gültig ist, destsz Null-Bytes in das Zielarray geschrieben.

Hinweise

memmove kann verwendet werden, um den effective type eines Objekts festzulegen, das durch eine Allokationsfunktion erhalten wurde.

Obwohl spezifiziert "als ob" ein temporärer Puffer verwendet würde, verursachen tatsächliche Implementierungen dieser Funktion weder den Overhead noch doppeltes Kopieren oder zusätzlichen Speicher. Ein gängiger Ansatz (glibc und bsd libc) ist, Bytes vorwärts vom Anfang des Puffers zu kopieren, wenn das Ziel vor der Quelle beginnt, und rückwärts vom Ende andernfalls, mit einem Fallback auf das effizientere memcpy wenn es überhaupt keine Überlappung gibt.

Wo strict aliasing die Untersuchung desselben Speichers als Werte von zwei verschiedenen Typen verbietet, kann memmove zur Konvertierung der Werte verwendet werden.

Beispiel

#define __STDC_WANT_LIB_EXT1__ 1
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
    char str[] = "1234567890";
    puts(str);
    memmove(str + 4, str + 3, 3); // kopiere von [4,5,6] nach [5,6,7]
    puts(str);
    // Setze den effektiven Typ des allokierten Speichers auf int
    int* p = malloc(3 * sizeof(int)); // allokierter Speicher hat keinen effektiven Typ
    int arr[3] = {1, 2, 3};
    memmove(p, arr, 3 * sizeof(int)); // allokierter Speicher hat nun einen effektiven Typ
    // Neuinterpretation von Daten
    double d = 0.1;
    // int64_t n = *(int64_t*)(&d); // Verletzung des Strict-Aliasing
    int64_t n;
    memmove(&n, &d, sizeof d); // OK
    printf("%a ist %" PRIx64 " als int64_t\n", d, n);
#ifdef __STDC_LIB_EXT1__
    set_constraint_handler_s(ignore_handler_s);
    char src[] = "aaaaaaaaaa";
    char dst[] = "xyxyxyxyxy";
    int r = memmove_s(dst, sizeof dst, src, 5);
    printf("dst = \"%s\", r = %d\n", dst, r);
    r = memmove_s(dst, 5, src, 10); // Anzahl ist größer als destsz
    printf("dst = \"");
    for (size_t ndx = 0; ndx < sizeof dst; ++ndx)
    {
        char c = dst[ndx];
        c ? printf("%c", c) : printf("\\0");
    }
    printf("\", r = %d\n", r);
#endif
}

Mögliche Ausgabe:

1234567890
1234456890
0x1.999999999999ap-4 ist 3fb999999999999a als int64_t
dst = "aaaaayxyxy", r = 0
dst = "\0\0\0\0\0yxyxy", r = 22

Referenzen

  • C23-Standard (ISO/IEC 9899:2024):
  • 7.24.2.2 Die memmove-Funktion (S.: TBD)
  • K.3.7.1.2 Die memmove_s-Funktion (S.: TBD)
  • C17-Standard (ISO/IEC 9899:2018):
  • 7.24.2.2 Die memmove-Funktion (S. 264)
  • K.3.7.1.2 Die memmove_s-Funktion (S. 446)
  • C11-Standard (ISO/IEC 9899:2011):
  • 7.24.2.2 Die memmove-Funktion (S: 363)
  • K.3.7.1.2 Die memmove_s-Funktion (S: 615)
  • C99-Standard (ISO/IEC 9899:1999):
  • 7.21.2.2 Die memmove-Funktion (S. 326)
  • C89/C90 Standard (ISO/IEC 9899:1990):
  • 4.11.2.2 Die memmove-Funktion

Siehe auch

kopiert einen Puffer in einen anderen
(Funktion)
kopiert eine bestimmte Anzahl von Breitzeichen zwischen zwei, möglicherweise überlappenden, Arrays
(Funktion)
C++-Dokumentation für memmove