Domanda

Ecco uno scenario particolare di cui non sono stato chiaro (in termini di ambito) da molto tempo.

considera il codice

#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;
}

l'output è

value is 502, 100

Quello che mi confonde un po 'è il seguente. La dichiarazione

t_t x

è dichiarato nell'ambito del test funzionale. Quindi, da quello che ho letto sulla programmazione in C, dovrebbe essere spazzatura fuori da questo ambito. Eppure restituisce un risultato corretto. È perché il " = " sulla linea      s.t = x; copia i valori di x in s.t?

Modifica ---

dopo alcuni esperimenti

#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;
}

produce effettivamente

value is 134513915, 7446516

come previsto.

È stato utile?

Soluzione

  

È perché il " = " sulla riga s.t = x; copia i valori di x in s.t?

Sì.

A proposito, questo è C ++. Hai superato il " s " da locale a principale come riferimento alla funzione, che la modifica. Poiché è un riferimento e non una copia, influisce sul "chiamante".

del chiamante

Altri suggerimenti

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

Nel tuo primo test , stai istruendo il compilatore a copiare il valore di x in st - funziona come previsto. La variabile locale x non rientra nell'ambito di applicazione, ma non viene mai referenziata al di fuori della funzione: i dati inizialmente contenuti vengono copiati nel membro t di main () s della variabile locale . Sarebbe effettivamente lo stesso se invece scrivessi:

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

Nel secondo test , si assegna un puntatore a un altro puntatore, entrambi dichiarati come variabili locali. Questo non fa nulla di utile - il valore in s.t rimane non inizializzato. Ho annotato il codice per aiutarti a seguirlo:

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

Leggi questo: Copia predefinita- costruttori e operatori di incarichi

Non fornendo un operatore di assegnazione, struct _s_t eseguirà una copia superficiale di tutti i suoi membri quando viene assegnato. Poiché stai memorizzando tutto in _t_t in base al valore, tutti i dati vengono copiati in base al valore.

Il problema che stai descrivendo è quando _t_t contiene un puntatore ai dati.

nel caso:

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;
}

Ciò causerebbe un problema, poiché t_t verrebbe distrutto alla fine di test () a quel punto quel puntatore non sarebbe valido.

ETA: perché hai aggiunto altro alla domanda ...

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

Qui hai creato un problema diverso. Quello che è successo lì è che hai creato un puntatore all'indirizzo di s.t, che va bene. Tuttavia, hai quindi riassegnato quel puntatore in modo che punti a x (questo compito, non ha fatto nulla per s.t, stai solo cambiando ciò a cui punta il puntatore pt) Il motivo per cui l'output è "come previsto" è perché stai solo leggendo lo stato non inizializzato della struttura.

Hai ragione, la linea

s.t = x;

copierà i valori.

Un'assegnazione copia il valore da una variabile a un'altra variabile. Quindi, sebbene la x locale originale sia sparita, ne hai una copia in s.

Sarebbe abbastanza diverso quando hai appena assegnato un puntatore a x:

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;
}

Quindi avresti un problema: hai solo l'indirizzo di x ma x non c'è più. Quindi hai effettivamente un riferimento a una posizione di memoria non valida. Il comportamento di questo programma sarebbe allora indefinito.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top