Namensräume
Varianten
Aktionen

memmove, memmove_s

Von cppreference.com
< 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 aus dem Objekt, auf das src zeigt, in das Objekt, auf das dest zeigt. Beide Objekte werden als Arrays von unsigned char interpretiert. Die Objekte dürfen sich überlappen: Das Kopieren erfolgt so, als ob die Zeichen in ein temporäres Zeichenarray kopiert und dann die Zeichen aus dem Array in dest kopiert würden.
Das Verhalten ist undefiniert, wenn auf Bereiche außerhalb des Ziels zugegriffen wird. Das Verhalten ist undefiniert, wenn dest oder src ein ungültiger oder Nullzeiger ist.
2) Ähnlich wie (1), aber beim Erkennen der folgenden Fehler zur Laufzeit wird der gesamte Zielbereich [dest, dest + destsz) (falls sowohl dest als auch destsz gültig sind) mit Nullen überschrieben und die aktuell installierte Constraint-Handler-Funktion aufgerufen.
  • dest oder src ist ein Nullzeiger
  • destsz oder count ist größer als RSIZE_MAX
  • count ist größer als destsz (Pufferüberlauf würde auftreten)
Das Verhalten ist undefiniert, wenn die Größe des Zeichenarrays, auf das dest zeigt, < count ist und count <= destsz; mit anderen Worten, ein fehlerhafter Wert von destsz deckt den drohenden Pufferüberlauf nicht auf.
Wie bei allen grenzgeprüften Funktionen ist memmove_s nur dann garantiert verfügbar, wenn __STDC_LIB_EXT1__ von der Implementierung definiert ist und wenn der Benutzer __STDC_WANT_LIB_EXT1__ auf die ganzzahlige Konstante 1 setzt, bevor <string.h> eingeschlossen wird.

Inhalt

[bearbeiten] Parameter

dest - Zeiger auf das zu kopierende Objekt
destsz - maximale Anzahl von Bytes, die im Ziel modifiziert werden sollen (typischerweise die Größe des Zielobjekts)
src - Zeiger auf das zu kopierende Objekt
zählt - Anzahl der zu kopierenden Bytes

[bearbeiten] Rückgabewert

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

[bearbeiten] Hinweise

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

Obwohl spezifiziert ist, "als ob" ein temporärer Puffer verwendet würde, verursachen tatsächliche Implementierungen dieser Funktion weder den Aufwand noch das doppelte Kopieren oder zusätzlichen Speicher. Ein üblicher Ansatz (glibc und bsd libc) ist, Bytes von vorne im Puffer zu kopieren, wenn das Ziel vor der Quelle beginnt, und andernfalls von hinten, wobei bei keinerlei Überlappung auf das effizientere memcpy zurückgegriffen wird.

Wo Strict Aliasing die Untersuchung desselben Speichers als Werte zweier verschiedener Typen verbietet, kann memmove verwendet werden, um die Werte umzuwandeln.

[bearbeiten] 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); // copy from [4,5,6] to [5,6,7]
    puts(str);
 
    // setting effective type of allocated memory to be int
    int* p = malloc(3 * sizeof(int)); // allocated memory has no effective type
    int arr[3] = {1, 2, 3};
    memmove(p, arr, 3 * sizeof(int)); // allocated memory now has an effective type
 
    // reinterpreting data
    double d = 0.1;
    // int64_t n = *(int64_t*)(&d); // strict aliasing violation
    int64_t n;
    memmove(&n, &d, sizeof d); // OK
    printf("%a is %" PRIx64 " as an 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); // count is greater than 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 is 3fb999999999999a as an int64_t
dst = "aaaaayxyxy", r = 0
dst = "\0\0\0\0\0yxyxy", r = 22

[bearbeiten] Referenzen

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

[bearbeiten] Siehe auch

kopiert einen Puffer in einen anderen
(Funktion) [bearbeiten]
kopiert eine bestimmte Anzahl breiter Zeichen zwischen zwei, möglicherweise überlappenden, Arrays
(Funktion) [bearbeiten]
C++-Dokumentation für memmove