Frage

Hier ist ein spezielles Szenario, das ich unklar gewesen sein (in Bezug auf Umfang) für eine lange Zeit.

Sie den Code betrachten

#include <stdio.h>


typedef struct _t_t{
    int x;
    int y;
} t_t;

typedef struct _s_t{
    int a;
    int b;
    t_t t;
}s_t;

void test(s_t & s){
    t_t x = {502, 100};
    s.t = x;
}


int main(){
    s_t s; 
    test(s);

    printf("value is %d, %d\n", s.t.x, s.t.y);
    return 0;
}

ist der Ausgang

value is 502, 100

Was ist ein wenig verwirrend für mich ist die folgende. Die Deklaration

t_t x

wird im Rahmen des Funktionstests erklärt. Also von dem, was ich über die C-Programmierung gelesen habe, sollte es Müll aus diesem Bereich sein. Doch es gibt ein korrektes Ergebnis. Ist es, weil die „=“ auf der Leitung      s.t = x; kopiert die Werte von x in s.t?

bearbeiten ---

Nach einigen Experimenten

#include <stdio.h>


typedef struct _t_t{
    int x;
    int y;
} t_t;

typedef struct _s_t{
    int a;
    int b;
    t_t t;
}s_t;

void test(s_t & s){
    t_t x = {502, 100};
    t_t * pt = &(s.t);
    pt = &x;
}


int main(){
    s_t s; 
    test(s);

    printf("value is %d, %d\n", s.t.x, s.t.y);
    return 0;
}

tatsächlich gibt

value is 134513915, 7446516

wie erwartet.

War es hilfreich?

Lösung

  

Ist es, weil die "=" auf der Linie s.t = x; kopiert die Werte von x in s.t?

Ja.

Übrigens ist diese C ++. Sie haben die „s“ local to main als Verweis auf die Funktion übergeben, die sie modifiziert. Da es sich um eine Referenz ist, und nicht eine Kopie, er betrifft des Anrufers „s“.

Andere Tipps

   t_t x = {502, 100};
   s.t = x;

In Ihrem ersten Test , du bist der Compiler anweist Kopie der Wert von x in s.t - dies funktioniert wie erwartet. Die lokale Variable x geht aus Umfang, ist aber nie außerhalb der Funktion verwiesen wird - die Daten, die sie in das t Mitglied main() der lokalen Variablen s anfänglich enthaltenen kopiert. Es wäre effektiv das gleiche, wenn Sie stattdessen schreibt:

t_t x = {502, 100};
s.t.x = x.x;
s.t.y = x.y;

In Ihrem zweiten Test , können Sie einen Zeiger auf einen anderen Zeiger zuweisen, die beide als lokale Variablen deklariert sind. Dies tut nichts nützlich - der Wert in s.t uninitialized bleibt. Ich habe den Code mit Anmerkungen versehen, damit Sie es wie folgt vor:

t_t x = {502, 100}; // local variable x initialized with 502, 100
t_t * pt = &(s.t); // local variable pt initialized with ADDRESS OF s.t
pt = &x; // local variable pt re-assigned to hold address of local variable x

// local variables go out of scope, output parameter s remains unmodified

Lesen Sie dies: Standard Kopier- und Zuweisungsoperator

Durch den Verzicht auf einen Zuweisungsoperator bereitstellt, wird die Struktur _s_t tun, um eine seichte-Kopie aller ihrer Mitglieder, wenn sie zugeordnet ist. Weil Sie alles in _t_t von Wert speichern, wird alle Daten von Wert kopiert.

Das Problem, das Sie beschreiben, ist, wenn _t_t einen Zeiger auf die Daten enthält.

im Fall:

typedef struct _s_t{
        int a;
        int b;
        t_t* t;
}s_t;

void test(s_t & s){
        t_t x = {502, 100};
        s.t = &x;
}

Dies würde ein Problem verursachen, wie t_t am Ende des Tests zerstört werden würde (), an dem Punkt, den Zeiger ungültig sein würde.

ETA: Weil Sie mehr auf die Frage hinzugefügt ...

void test(s_t & s){
     t_t x = {502, 100};
     t_t * pt = &(s.t);
     pt = &x;
}

Sie haben ein anderes Problem hier erstellt. Was passiert ist Sie einen Zeiger auf die Adresse des s.t erstellt haben, was in Ordnung ist. Allerdings haben Sie dann diesen Zeiger neu zugewiesen x-zu-Punkt (diese Zuordnung nichts tat, um s.t, ändern Sie genau das, was der Zeiger pt Punkte) Der Grund für die Ausgabe ‚wie erwartet‘ ist, weil Sie gerade den uninitialised Zustand der Struktur zu lesen.

Du hast Recht, die Zeile

s.t = x;

die Werte kopieren über.

Ein asignment kopiert den Wert von einer Variablen in einer anderen Variable. Obwohl also die ursprüngliche lokal x gegangen ist, haben Sie eine Kopie in s bekommen.

Es wäre ganz anders, wenn man nur einen Zeiger auf x zugewiesen hat:

typedef struct _s_t{
        int a;
        int b;
        t_t* t;
}s_t;

void test(s_t & s){
        t_t x = {502, 100};
        s.t = &x;
}

Dann würden Sie ein Problem haben: Sie haben nur die Adresse von x aber x ist weg. So haben Sie effektiv einen Verweis auf einen ungültigen Speicherplatz haben. Das Verhalten dieses Programm würde dann nicht definiert werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top