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 werdenmemmove()。

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 invoid*)。
  • str2: Quelladresse, zeigt auf die Startposition der zu kopierenden Daten (Typumwandlung inconst 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 <stdio>
#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:

  1. In Szenario 1,destundsrcsind zwei unabhängige Arrays, keine Überlappung,memmove(dest, src, 9)wirdsrcdie ersten 9 Bytes werden unverändert kopiert nachdest。
  2. 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.
  3. Wenn Szenario 2 ersetzt wird durchmemcpy, 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 <stdio>
#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 <stdio>
#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 <stdio>
#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.

C-Standardbibliothek - string.h

Weitere Erweiterungen