2016-07-27 7 views
-1

Mit einer partiellen Kopie würde ich erwarten, die übereinstimmenden Felder mit einer Kopie zu setzen, aber die nicht übereinstimmenden Felder nicht gesetzt (d. H. Behalten ihre vorherigen Werte).Können Sie eine Instanz einer Struktur teilweise in eine andere Anweisung eines anderen Typs kopieren?

Es scheint nicht zu passieren. Ich bin neugierig warum und ob das ein undefiniertes Verhalten ist?

#include <stdio.h> 

#define print_base(s) printf("%d %d\n", s.a, s.b) 
#define print_extended(s) printf("%d %d %d\n", s.a, s.b, s.c) 

typedef struct 
{ 
    int a; 
    int b; 
} base; 

typedef struct 
{ 
    int a; 
    int b; 
    int c; 
} extended; 

int main() 
{ 
    base s1 = {1,2}; 
    extended s2 = {0}; 
    extended s3 = {0}; 
    extended s4 = {4,5,6}; 
    extended s5 = {4,5,6}; 
    extended s6 = {7,8,9}; 
    base s7 = {0}; 

    print_extended(s2); 
    s2 = *(extended*)&s1; 
    print_extended(s2); 

    print_extended(s3); 
    memcpy(&s3, &s1, sizeof(s3)); 
    print_extended(s3); 

    print_extended(s4); 
    s4 = *(extended*)&s1; 
    print_extended(s4); 

    print_extended(s5); 
    memcpy(&s5, &s1, sizeof(s5)); 
    print_extended(s5); 

    /* lossy copy */ 
    print_base(s7); 
    s7 = *(base*)&s6; 
    print_base(s7); 

    return 0; 
} 

/* 
Actual Expected 
0 0 0 0 0 0 
1 2 1 1 2 0 
0 0 0 0 0 0 
1 2 1 1 2 0 
4 5 6 4 5 6 
1 2 1 1 2 6 
4 5 6 4 5 6 
1 2 1 1 2 6 
0 0  0 0 
7 8  7 8 
*/ 
+2

Nicht definiertes Verhalten für den Zugriff über die Grenzen eines Objekts in 'memcpy (& s3, & s1, sizeof (s3));' da 'sizeof (s1)' kleiner als 'sizeof (s3)' ist. – EOF

+0

Ist das 'struct' Tag oder was? –

Antwort

0
s2 = *(extended*)&s1; 

Dieses Verhalten nicht definiert hat, wird das Objekt an &s1 nicht vom richtigen Typ über einen Zeiger von extended* Typ zugegriffen werden kann.

memcpy(&s3, &s1, sizeof(s3)); 

Dies auch nicht definiertes Verhalten hat, weil Sie sizeof(extended) Bytes von einem Objekt zu lesen, die lange nur sizeof(base) Bytes.

Wenn Sie darüber nachdenken, wird es offensichtlich nicht wie erwartet funktionieren. Wenn Sie eine extended-Struktur kopieren, liest der Compiler drei Wörter (d. H. sizeof(extended)) aus der Quelle und kopiert diese drei Wörter an das Ziel. Es kopiert nicht weniger als drei Wörter und lässt das letzte Wort unverändert. Sie haben ihm gesagt, sizeof(extended) Bytes von der Adresse &s1 zu lesen, also ist es genau das, was es tut. Und das letzte Mitglied wird auf einen Müllwert gesetzt, weil Sie es von einem Speicherplatz lesen, der nicht Teil von s1 ist und einen Müllwert enthält.

Warum erwarten Sie, dass der Compiler sizeof(base) Bytes kopiert, wenn Sie ihm sagen, sizeof(extended) Bytes zu kopieren? Wenn Sie nicht möchten, dass es mehr Bytes kopiert, dann sagen Sie ihm nicht, mehr Bytes zu kopieren!

+0

Ich denke, du möchtest: memcpy (& s3, & s1, sizeof (base)); anstatt: memcpy (& s3, & s1, sizeof (erweitert)); ... um nur die ersten 2 Felder zu kopieren. –

+0

Ja, natürlich. Wenn Sie nur den Inhalt von 's1' kopieren wollen, dann sagen Sie ihm nicht, dass er's1' plus, was auch immer passiert, hinterher im Speicher ist! –

0

beim Kopieren von einem Speicherplatz an einen anderen mit Zeiger Abgüsse sind Sie im Grunde

Diese Aussagen ‚die Dinge selbst in die Hand zu nehmen‘:

s2 = *(extended*)&s1; 
s1 = *(base*)&s2; 

gleichwertig sind diese:

memcpy(&s2, &s1, sizeof(extended)); 
memcpy(&s1, &s2, sizeof(base)); 

Ich denke, es ist klar, warum Kopieren von Basis * Quelle zu erweitert * dest überschreibt nur einen Teil der Daten und andersherum kann dies verheerende Folgen haben (Sie haben einen unzulässigen Speicherzugriff und können wichtige Daten überschreiben).

Verwandte Themen