Funções, struct e ponteiros

From Applied Science

Ponteiros para struct são um modo prático de acessar membros de uma struct. O conceito de ponteiros para struct é o mesmo que ponteiro para uma variável int ou float por exemplo. Primeiro declaramos uma variável e um ponteiro para ela, depois fazemos o ponteiro apontar para o endereço de memória daquela variável. A vantagem de um ponteiro para uma struct é que uma função pode receber apenas um ponteiro para um membro da struct, sem precisar receber toda struct de uma vez.

Erros de lógica:

  • Se o ponteiro para a struct não estiver apontado para a mesma, a tentativa de acessar um membro da struct causará um travamento ou outro erro;
  • O tipo declarado dentro da struct deve corresponder ao tipo do ponteiro em si e vice-versa para evitar problemas.


Para entender os exemplos abaixo você precisa entender bem ponteiros, funções e structs


  • A function that swaps all values of all members of two structs of the same type:
typedef struct Produto Pro;

struct Produto {
    char Tipo[1];
    int  Ano;
};

/* recebe dois endereços de duas structs, A e B, e troca os valores de todos os membros de cada uma */
void Troca (Pro *A, Pro *B) {
    Pro Temp, *C;
    C = &Temp;
    *C = *A;
    *A = *B;
    *B = *C;
}

/* Chamando a função */
Troca(&X, &Y);

É a mesma lógica da troca de valores de duas variáveis, mas agora temos structs e ponteiros para uma struct. Note que ambas as structs devem ser do mesmo tipo, senão o programa não compila.

Nota: no exemplo acima, X e Y são do mesmo tipo "Pro". Se um membro da struct é do tipo float e o ponteiro é do tipo int. Esse tipo de mistura causa problemas.


  • Uma função que troca o valor de dois membros de duas structs:
typedef struct Product Pro;

struct Produto {
    char Tipo[1];
    int  Ano;
};

/* Recebe dois endereços de duas structs, A e B e troca os valores do membro "Ano" de cada uma */
void Troca (Pro *A, Pro *B) {
    Pro Temp, *C;
    C = &Temp;
    C->Ano = A->Ano;
    A->Ano = B->Ano;
    B->Ano = C->Ano;
}

/* Chamando a função */
Swap(&X, &Y);

O operator flecha: tanto C->Ano quanto (*C).Ano significam a mesma coisa. No segundo caso os parêntesis são obrigatórios por causa da precedência dos operadores. Sem os parêntesis o compilador irá ler *(C.Ano) e gerará um erro porque não tem um ponteiro com aquele nome. O operador flecha é um símbolo mnemônico para lembrar que C é um ponteiro e que aponta para a struct do tipo "Pro", em direção ao membro "Ano".

Nota: temos que ter cuidado para não confundir o ponteiro para uma struct com a própria struct. Portanto, se escrevermos C.Ano ou B.Tipo[0], estamos dizendo para o compilador que "C" e "B" são structs quando não o são.