Pergunta

Aqui é um cenário específico que eu tenho sido claro sobre (em termos de escopo) para um longo tempo.

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

a saída é

value is 502, 100

O que é um pouco confuso para mim é o seguinte. A declaração

t_t x

é declarada no âmbito do teste de função. Assim, desde que eu li sobre programação C, que deve ser lixo para fora deste âmbito. No entanto, ele retorna um resultado correto. Será que é porque o "=" na linha s.t = x; copia os valores de x em s.t?

editar ---

Depois de algumas experiências

#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 saídas

value is 134513915, 7446516

como esperado.

Foi útil?

Solução

Será que é porque o "=" na s.t line = x; copia os valores de x em s.t?

Sim.

A propósito, este é C ++. Você passou o "s" local principal como uma referência para a função, que modifica. Porque é uma referência, e não uma cópia, isso afeta "s" do chamador.

Outras dicas

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

Em seu primeiro teste , você está instruindo o compilador cópia o valor de x em s.t - Isso funciona como esperado. O x variável local sai do escopo, mas nunca é referenciado fora da função - os dados que continha inicialmente é copiado para o membro t de main() variável local do s. Seria efetivamente o mesmo se você escreveu em vez disso:

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

No seu segundo teste , você atribui um ponteiro para outro ponteiro, sendo que ambos são declarados como variáveis ??locais. Isso não faz nada útil - valor, em s.t permanece não inicializado. Eu tenho anotado o código para ajudá-lo a segui-lo:

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

Leia Isto: padrão contra cópia construtores e operadores de atribuição

Por não fornecer um operador de atribuição, o _s_t struct vai fazer um rasas-cópia de todos os seus membros quando for atribuído. Porque você está armazenando tudo em _t_t por valor, todos os dados são copiados por valor.

O problema que você está descrevendo é quando _t_t contém um ponteiro para os dados.

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

Isto causaria um problema, como T_T seria destruído no final do teste () no ponto em que esse ponteiro seria inválido.

ETA: Como você adicionou mais à pergunta ...

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

Você criou um problema diferente aqui. O que aconteceu não é ter criado um ponteiro para o endereço de s.t, o que é bom. No entanto você, em seguida, transferido esse ponteiro para apontar para x (esta atribuição, não fez nada para s.t, você está apenas mudando o que pontos o PT ponteiro para) O motivo da saída é 'como esperado' é porque você está apenas lendo o estado uninitialised da estrutura.

Você tem razão, a linha

s.t = x;

irá copiar os valores acima.

Um asignment copia o valor de uma variável para outra variável. Assim, embora o local original x se foi, você tem uma cópia em s.

Seria muito diferente quando você acabou de atribuir um ponteiro para 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;
}

Em seguida, você teria um problema: você só tem o endereço de x, mas x está desaparecido. Então você efetivamente tem uma referência a um local de memória inválido. O comportamento deste programa seria indefinida em seguida.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top