Pregunta

Aquí hay un escenario particular sobre el que no he tenido claro (en términos de alcance) durante mucho tiempo.

considere el código

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

la salida es

value is 502, 100

Lo que es un poco confuso para mí es lo siguiente. La declaración

t_t x

se declara en el alcance de la prueba de función. Entonces, de lo que he leído sobre la programación en C, debería ser basura fuera de este alcance. Sin embargo, devuelve un resultado correcto. ¿Es porque el " = " en la línea      s.t = x; copia los valores de x en s.t?

editar ---

después de algo de experimentación

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

realmente produce

value is 134513915, 7446516

como se esperaba.

¿Fue útil?

Solución

  

¿Es porque el " = " en la línea s.t = x; copia los valores de x en s.t?

Sí.

Por cierto, esto es C ++. Has pasado la " s " local a main como referencia a la función, que la modifica. Debido a que es una referencia, y no una copia, afecta la " s " de la persona que llama.

Otros consejos

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

En su primera prueba , le indica al compilador que copie el valor de x en st - Esto funciona como se esperaba. La variable local x queda fuera del alcance, pero nunca se hace referencia fuera de la función: los datos que contenía inicialmente se copian en el miembro t de main () la variable local s . Sería efectivamente lo mismo si en su lugar escribieras:

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

En su segunda prueba , asigna un puntero a otro puntero, ambos declarados como variables locales. Esto no hace nada útil: el valor en s.t permanece sin inicializar. He anotado el código para ayudarlo 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

Lea esto: Copia predeterminada- constructores y operadores de asignación

Al no proporcionar un operador de asignación, la estructura _s_t realizará una copia superficial de todos sus miembros cuando se asigne. Debido a que está almacenando todo en _t_t por valor, todos los datos se copian por valor.

El problema que está describiendo es cuando _t_t mantiene un puntero a los datos.

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

Esto causaría un problema, ya que t_t se destruiría al final de la prueba () en cuyo punto ese puntero sería inválido.

ETA: Porque agregaste más a la pregunta ...

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

Has creado un problema diferente aquí. Lo que sucedió allí es que ha creado un puntero a la dirección de s.t, lo cual está bien. Sin embargo, luego ha reasignado ese puntero para que apunte a x (esta asignación, no hizo nada a s.t, solo está cambiando lo que apunta el puntero pt) La razón por la que la salida es 'como se esperaba' es porque solo está leyendo el estado no inicializado de la estructura.

Tienes razón, la línea

s.t = x;

copiará los valores.

Una tarea copia el valor de una variable a otra variable. Entonces, aunque la x local original desapareció, tienes una copia en s.

Sería muy diferente cuando acaba de asignar un puntero 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;
}

Entonces tendría un problema: solo tiene la dirección de x pero x se ha ido. Así que efectivamente tiene una referencia a una ubicación de memoria no válida. El comportamiento de este programa sería indefinido entonces.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top