pointer als dest bei memcpy/strcpy



  • Hey, bin gerade auf folgendes Problem gestoßen:

    folgendes funktioniert:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        char* string2="new";
        char string1[4]="old";
        memcpy(string1, string2, strlen(string2));
        printf("%s",string1);
        return 0;
    }
    

    dies hier aber nicht:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        char* string2="new";
        char* string1="old";
        memcpy(string1, string2, strlen(string2));
        printf("%s",string1);
        return 0;
    }
    

    kann mir nicht ganz erklären warum, es sollte doch equivalent sein?



  • Nein es ist nicht Äquivalent. Ein Zeiger ist kein Array. Ein Zeiger kann aber auf ein Array zeigen. Dein Stringliteral selber liegt übrigens in einem readonly Bereich und darf demzufolge nicht überschrieben werden.



  • wieso sollte das in diesem kontext einen Unterschied machen? strlen ist nicht von betroffen, und die Adresse die übergeben wird sollte in beiden Fällen gleich sein, nämlich die des ersten Elements.
    memcpy(&string1[0], &string2[0], strlen(string2));
    führt zu keinem Unterschied

    und selbst wenn die daten in .rodata liegen, sollte es doch nichts machen, weil Länge der Ziel und Quelldaten übereinstimmen.



  • Du darfst aber dahin nichts schreiben.
    Zu dem Rest gibt es hier jeden Tag die selben Fragen. Schau dich also einfach mal um, da wird dir geholfen.



  • Tatsache, bei
    char string1[]="old";
    wird der String in einem völlig anderem Speicherbereich erstellt als bei
    char* string1="old";
    (siehe &stringX[0])

    Das ist jetzt wirklich nichts was ich oft gesehen hätte.
    Komisch das dafür kein const nötig ist, damit es in einem geschützten Speicherbereich landet.

    Ist das evtl. Compilerabhängig oder wie ist das im Standard geregelt?



  • AFAIK ist das im Standard geregelt, dass Stringliterale nicht modifizierbar sind, während Arrays modifizierbar sind, wenn sie nicht const sind.



  • "Ein Array ist kein Zeiger" ist natürlich richtig, passt für diesen Kontext aber nicht. Beispielsweise wäre durchaus legal:

    int main()
    {
        char* string2="new";
        char* string1=malloc(4); strcpy(string1,"old");
        memcpy(string1, string2, strlen(string2));
        printf("%s",string1);
        return 0;
    }
    

    Wobei string1 nach wie vor ein Zeiger ist, der hierbei aber nicht mit einem Stringliteral initialisiert wird.
    Prinzipiell kannst du dir merken, dass bei

    char* string2="new";
    

    immer implizit ein const gilt:

    const char* string2="new";
    

    wobei der C Standard lediglich vorschreibt, dass das Stringliteral in einem Readonly-Speicherbereich angelegt werden kann (aber nicht muss).



  • Wutz schrieb:

    "Ein Array ist kein Zeiger" ist natürlich richtig, passt für diesen Kontext aber nicht. Beispielsweise wäre durchaus legal:

    Ich denke, diese Aussage ist kontext unabhängig richtig und das war genau das Problem hier, orioon hat sie als gleich angesehen.

    Außerdem spielst du in deinem Bsp. weiterhin nur mit Zeigern.



  • ich habe sie nicht als gleich angesehen, sondern IM KONTEXT als gleich angesehen, mir sind die Unterschiede durchaus bewusst.
    Und diese Annahme wäre auch richtig, wenn nicht implizit ein const zustande kommen würde.

    Das mit dem malloc habe ich auch rausgefunden, das funktioniert wunderbar dann 🙂
    Ist nochmal ein eigener Speicherbereich sogar dann.


Anmelden zum Antworten