strcpy vs. memcpy

81

Was ist der Unterschied zwischen memcpy()und strcpy()? Ich habe versucht, es mit Hilfe eines Programms zu finden, aber beide geben die gleiche Ausgabe.

int main()
{
    char s[5]={'s','a','\0','c','h'};
    char p[5];
    char t[5];
    strcpy(p,s);
    memcpy(t,s,5);
    printf("sachin p is [%s], t is [%s]",p,t);
    return 0;
}

Ausgabe

sachin p is [sa], t is [sa]
Sachin Chourasiya
quelle

Antworten:

126

Was könnte getan werden, um diesen Effekt zu sehen?

Kompilieren Sie diesen Code und führen Sie ihn aus:

void dump5(char *str);

int main()
{
    char s[5]={'s','a','\0','c','h'};

    char membuff[5]; 
    char strbuff[5];
    memset(membuff, 0, 5); // init both buffers to nulls
    memset(strbuff, 0, 5);

    strcpy(strbuff,s);
    memcpy(membuff,s,5);

    dump5(membuff); // show what happened
    dump5(strbuff);

    return 0;
}

void dump5(char *str)
{
    char *p = str;
    for (int n = 0; n < 5; ++n)
    {
        printf("%2.2x ", *p);
        ++p;
    }

    printf("\t");

    p = str;
    for (int n = 0; n < 5; ++n)
    {
        printf("%c", *p ? *p : ' ');
        ++p;
    }

    printf("\n", str);
}

Es wird diese Ausgabe erzeugen:

73 61 00 63 68  sa ch
73 61 00 00 00  sa

Sie können sehen, dass das "ch" von kopiert wurde memcpy(), aber nicht strcpy().

Egrunin
quelle
1
Hallo, ich weiß, dass der Beitrag alt ist, aber ich habe zwei Fragen dazu. Erstens - printf("%2.2x ", *p);- warum haben Sie printf auf 2.2 beschränkt? Außerdem kann ich KEINEN Punkt sehen ... Zweitens - printf("%c", *p ? *p : ' ');- was prüft dieser Test wirklich? Wenn *p? Vielen Dank im Voraus für Ihre Antwort!
Peter Cerba
14
In einer printf-Anweisung bedeutet "x" "Basis 16". "2.2" bedeutet: zwei und nur zwei Ziffern. Der *pTest bedeutet: "Wenn Sie eine Null treffen, drucken Sie ein Leerzeichen."
Egrunin
85

strcpystoppt, wenn es auf ein NUL ( '\0') - Zeichen memcpytrifft, nicht. Sie sehen den Effekt hier nicht, da %sprintf auch bei NUL stoppt.

Yann Ramin
quelle
2
@Sachin: initialisieren pund tzu etwas (alle Rohlinge, zum Beispiel), dann nach dem Kopieren, zu vergleichen , p[3]zu t[3]. Das strcpyging nicht darüber hinaus p[2], wo es das Nullzeichen fand, sondern das memcpywie angegeben fünf Zeichen kopierte.
Cascabel
9
Minor nit-pick: strcpy stoppt, wenn es auf das NUL-Zeichen trifft (ein "L"). NULL (zwei "L") ist eine Kompilierungszeitkonstante für einen Zeiger, der garantiert nicht auf ein gültiges Objekt zeigt.
Daniel Stutzbach
Danke, ich habe die Antwort bekommen
Sachin Chourasiya
Wenn sich dest und src überschneiden, wird strcpy einen Seg-Fehler auslösen?
Alcott
12

strcpyWird beendet, wenn der Nullterminator der Quellzeichenfolge gefunden wird. memcpyerfordert die Übergabe eines Größenparameters. In dem von Ihnen präsentierten Fall wird die printfAnweisung angehalten, nachdem der Nullterminator für beide Zeichenarrays gefunden wurde. Sie werden jedoch auch Daten darin finden t[3]und t[4]kopiert haben.

fbrereto
quelle
9

strcpy Kopiert das Zeichen nacheinander von der Quelle zum Ziel, bis es in der Quelle das Zeichen NULL oder '\ 0' findet.

while((*dst++) = (*src++));

Dabei werden memcpyDaten (nicht Zeichen) von der Quelle zum Ziel der angegebenen Größe n kopiert, unabhängig von den Daten in der Quelle.

memcpysollte verwendet werden, wenn Sie gut wissen, dass die Quelle andere als Zeichen enthält. Für verschlüsselte oder binäre Daten ist memcpy der ideale Weg.

strcpyist veraltet, also verwenden strncpy.

Viswesn
quelle
3

Aufgrund des Nullzeichens in Ihrer sZeichenfolge printfwird darüber hinaus nichts angezeigt. Der Unterschied zwischen pund twird in den Zeichen 4 und 5 sein. Sie pwerden keine haben (sie werden Müll sein) und twerden das 'c'und haben 'h'.

Thomas Jones-Low
quelle
2
  • Verhaltensunterschied: strcpystoppt, wenn es auf ein NULLoder trifft'\0'
  • Leistungsunterschied: Ist in der memcpyRegel effizienter als das strcpy, bei dem immer die kopierten Daten gescannt werden
Eukken
quelle
2

Der Hauptunterschied besteht darin, dass memcpy()immer die genaue Anzahl der von Ihnen angegebenen Bytes kopiert wird. strcpy()Auf der anderen Seite wird kopiert, bis ein NUL-Byte (auch bekannt als 0) gelesen wird, und danach angehalten.

Jeremy Friesner
quelle
1

Das Problem mit Ihrem Testprogramm ist, dass das printf()Einfügen des Arguments beendet wird %s, wenn eine Nullterminierung auftritt \0. Also in Ihrer Ausgabe haben Sie wahrscheinlich nicht bemerkt, dass memcpy()die Zeichen cund hauch kopiert .

Ich habe in GNU gesehen glibc-2.24 , dass (für x86) strcpy()nur anruft memcpy(dest, src, strlen(src) + 1).

Jaspar L.
quelle
0

printf("%s",...) stoppt das Drucken der Daten, wenn null auftritt, sodass beide Ausgaben gleich sind.

Der folgende Code unterscheidet zwischen strcpyund memcpy:

#include<stdio.h>
#include<string.h>

int main()
{
    char s[5]={'s','a','\0','c','h'};
    char p[5];
    char t[5];
    int i;
    strcpy(p,s);
    memcpy(t,s,5);
    for(i=0;i<5;i++)
        printf("%c",p[i]);
        printf("\n");
    for(i=0;i<5;i++)
        printf("%c",t[i]);

    return 0;
}
abhijeet keshri
quelle