memmove, memmove_s
Von cppreference.com
| 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_snur 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
Führen Sie diesen Code aus
#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
| (C11) |
kopiert einen Puffer in einen anderen (Funktion) |
| (C95)(C11) |
kopiert eine bestimmte Anzahl breiter Zeichen zwischen zwei, möglicherweise überlappenden, Arrays (Funktion) |
| C++-Dokumentation für memmove
| |