C-Bibliotheksfunktion - memmove()
C-Standardbibliothek - string.h
memmove()ist die C-Standardbibliothek<string.h>Speicheroperationsfunktion darin, mit der eine angegebene Anzahl von Bytes von der Quelladresse an die Zieladresse kopiert werden kann und die überlappende Speicherfälle sicher behandeln kann.
Wortdefinitionen:memmoveJamemory moveAbkürzung für (memory move), was das Verschieben von Daten im Speicher bedeutet.
C-Bibliotheksfunktionenvoid *memmove(void *str1, const void *str2, size_t n)vonstr2KopierenBytes nachstr1。
Unterschied zu memcpy():
- Wenn der Zielbereich und der Quellbereich eine Speicherüberlappung aufweisen,
memmove()kann es garantieren, dass die überlappenden Bytes, bevor die Quelldaten überschrieben werden, zuerst sicher in den Zielbereich übertragen werden, daher im Vergleich zumemcpy()zuverlässiger. - wenn der Zielbereich und der Quellbereich überhaupt nicht überlappen,
memmove()das Verhalten undmemcpy()Dasselbe. - wenn unklar ist, ob die beiden Speicherbereiche überlappen, sollte vorrangig verwendet werden
memmove()。
Funktionsdeklaration
void *memmove(void *str1, const void *str2, size_t n)
Parameterbeschreibung
- str1: Zieladresse, zeigt auf den Speicherbereich, der zum Speichern des kopierten Inhalts verwendet wird (Typumwandlung in
void*)。 - str2: Quelladresse, zeigt auf die Startposition der zu kopierenden Daten (Typumwandlung in
const void*)。 - n: die Anzahl der zu kopierenden Bytes (
size_tTyp).
Rückgabewert
gibt einen Zeiger auf den Zielspeicherbereich zurückstr1Zeiger (derselbe wie der übergebenestr1derselbe).
Header-Datei
#include <string.h>
Beispiel
Beispiel 1: Grundlegende Verwendung
Das folgende Beispiel zeigtmemmove()Verwendung in sowohl nicht überlappenden als auch überlappenden Szenarien:
Beispiel
#include <string.h>
int main()
{
/* Szenario 1: nicht überlappende Speicherkopie */
char dest[] = "oldstring";
char src[] = "newstring";
printf("Vor nicht überlappender Kopie:dest = %s, src = %s\n", dest, src);
memmove(dest, src, 9);
printf("Nach nicht überlappender Kopie:dest = %s, src = %s\n", dest, src);
/* Szenario 2: überlappende Speicherkopie (wo memmove den Vorteil hat) */
char str[] = "123456789";
printf("\nVor überlappender Kopie:%s\n", str);
memmove(str + 2, str, 6);
printf(Nach überlappender Kopie: %s\n", str);
return 0;
}
Run result:
非重叠拷贝前:dest = oldstring, src = newstring 非重叠拷贝后:dest = newstring, src = newstring 重叠拷贝前:123456789 重叠拷贝后:121234569
Codeanalyse:
- In Szenario 1,
destundsrcsind zwei unabhängige Arrays, keine Überlappung,memmove(dest, src, 9)wirdsrcdie ersten 9 Bytes werden unverändert kopiert nachdest。 - In Szenario 2,
str + 2(destination) undstr(source) zeigt auf einen überlappenden Bereich innerhalb desselben Arrays,memmovespeichert zuerst die überschriebenen Daten, schließt dann die Kopie ab, sodass das Ergebnis korrekt ist. - Wenn Szenario 2 ersetzt wird durch
memcpy, kann auf einigen Compilern oder Plattformen zu falschen Ergebnissen führen, weilmemcpygarantiert nicht die Behandlung überlappender Fälle.
Beispiel 2: Umgang mit überlappendem Speicher
Wenn zwei Speicherbereiche einander überlappen,memmove()kann dennoch das korrekte Ergebnis liefern:
Beispiel
#include <string.h>
int main()
{
char str[] = "memmove can be very useful";
printf("Before: %s\n", str);
/* 7 Bytes ab Position 11 nach Position 5 kopieren; die beiden Bereiche überlappen sich */
memmove(str + 5, str + 11, 7);
printf("Nach: %s\n", str);
return 0;
}
Run result:
Before: memmove can be very useful After: memmove can be very useful
Codeanalyse:
- Im ursprünglichen String ist ab Position 5
"ve can be very useful", die 7 Bytes ab Position 11 sind"can be"(einschließlich des nachfolgenden Leerzeichens). memmove(str + 5, str + 11, 7)wird"can be"nach Position 5 verschoben, überlappen sich die beiden Bereiche, abermemmoveEs wählt abhängig von der Adressgröße eine Vorwärts- oder Rückwärtskopierstrategie, um die Datenintegrität sicherzustellen.- Nach dem Kopieren wird der Inhalt ab Position 5
"can be", während die übrigen Zeichen unverändert bleiben.
Beispiel 3: Vergleich von memcpy() und memmove()
Das folgende Beispiel zeigt, dass die beiden Funktionen im gleichen Überlappungsszenario unterschiedliche Ergebnisse liefern können:
Beispiel
#include <string.h>
int main()
{
char str1[] = "abcdefghij";
char str2[] = "abcdefghij";
printf("Original: %s\n", str1);
/* Verwendung von memcpy: Verhalten ist undefiniert bei Überlappung */
memcpy(str1 + 2, str1, 5);
printf("memcpy: %s\n", str1);
/* Verwendung von memmove: Verhalten ist garantiert bei Überlappung */
memmove(str2 + 2, str2, 5);
printf("memmove: %s\n", str2);
return 0;
}
Run result:
Original: abcdefghij memcpy: ababababij memmove: ababcdfghij
Beschreibung: In diesem Beispiel,memcpyDa das byteweise Vorwärtskopieren dazu führt, dass die Quelldaten früh überschrieben werden, entspricht die Ausgabe nicht den Erwartungen; währendmemmovees Überlappung erkennt und eine Rückwärtskopie verwendet, sodass das Ergebnis korrekt ist. Verschiedener Plattformen oder CompilermemcpyImplementierungsverhalten kann uneinheitlich sein, daher sollte es immer verwendet werden, wenn überlappende Szenarien auftreten.memmove。
Beispiel 4: Die angegebene Anzahl von Bytes kopieren
memmove()ist eine Operation auf Byte-Ebene und schreibt den String-Terminator nicht automatisch; bei der Verwendung müssen Sie ihn manuell hinzufügen.'\0':
Beispiel
#include <string.h>
int main()
{
char src[] = "Hello, World!";
char dest[20];
/* Nur die ersten 5 Bytes kopieren */
memmove(dest, src, 5);
dest[5] = '\0'; /* String-Terminator manuell hinzufügen */
printf("Quelle: %s\n", src);
printf("Ziel: %s\n", dest);
printf("Länge: %zu\n", strlen(dest));
return 0;
}
Run result:
Source: Hello, World! Dest: Hello Length: 5
Codeanalyse:
memmove(dest, src, 5)nur die ersten 5 Bytes kopieren ('H' 'e' 'l' 'l' 'o')。memmove()schreibt nicht automatisch an das Ende des Ziels'\0', falls weggelassendest[5] = '\0', nachfolgende Zeichenkettenoperationen (wie z. B.printf、strlen) wird unbestimmten Speicher lesen, was zu undefiniertem Verhalten führt.
Unterschied zu memcpy()
| Funktionen | memcpy() | memmove() |
|---|---|---|
| Umgang mit überlappendem Speicher | Das Verhalten ist undefiniert, was zu falschen Ergebnissen führen kann | Sichere Handhabung, die korrektes Kopieren gewährleistet |
| Implementierungsansatz | Direktes byteweises Kopieren in der Reihenfolge | Erkennt die Überlappungsrichtung, wählt Vorwärts- oder Rückwärtskopie |
| Leistung | Normalerweise etwas schneller (kein Overhead für die Überlappungserkennung) | Etwas langsamer (beinhaltet Logik zur Überlappungserkennung) |
| Verwendungshinweise | Verwenden, wenn bestätigt wird, dass sich Quelle und Ziel überhaupt nicht überlappen | Verwenden, wenn eine Überlappung vorliegt oder wenn unsicher ist, ob eine Überlappung vorliegt. |
Weitere Erweiterungen