Pointer to struct

Asked

Viewed 212 times

7

I was studying pointers to struct, and I saw that it has two ways to use. can be:

(*ponteiro).variavel

Or:

ponteiro->variavel

According to what I read, when we put *ponteiro.variavel, because of the order of precedence, he ends up understanding so:

*(ponteiro.variavel)

So, ok. While practicing (I was using ->), I came across the following situation:

I have a struct inside the other:

typedef struct {
    char nome[100];
    float salario;
} Funcionario;

typedef struct {
    char nome[100];
    unsigned qtdFuncionario;
    Funcionario *vetor;
} Firma;

When accessing the nome or the salario of the employee, I had to do the following:

vetor[firma->qtdFuncionario].nome

If I put:

vetor[firma->qtdFuncionario]->nome

The compiler doesn’t accept it! But why does it work? And the order of precedence?

Thanks for your help ;)

  • What do you mean "Compiler does not accept!" ?

2 answers

1

The member vetor is part of the structure Firma!

The compiler will return an error saying that vetor was not declared if you try something like:

vetor[firma->qtdFuncionario]->nome   /* ERRO! */

You need to tell the compiler that vetor is inside firma:

firma->vetor[firma->qtdFuncionario]->nome  /* OK (?) */

CARING:

The compiler will compile this code perfectly, however, if your intent is to store the size of vetor in qtdFuncionario, the code yet has a problem!

Something like:

firma->vetor[firma->qtdFuncionario]->nome   /* NÃO! */

Accesses an element after the last element of vetor, reading an unknown memory position, probably causing in an undefined behavior code.

Accesses the first functionary of vetor:

firma->vetor[ 0 ]->nome   /* OK! */

Accesses the last functionary of vetor:

firma->vetor[ firma->qtdFuncionario - 1 ]->nome  /* OK! */

Example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char nome[100];
    float salario;
} Funcionario;


typedef struct {
    char nome[100];
    unsigned int qtdFuncionario;
    Funcionario *vetor;
} Firma;

int main( void )
{
    unsigned int i;
    Firma f;

    /* Nome da Firma */
    strcpy( f.nome, "FooBar" );

    /* Quantidade de funcionarios */
    f.qtdFuncionario = 3;

    /* Aloca memoria para 3 funcionarios */
    f.vetor = (Funcionario*) malloc( sizeof(Funcionario) * 3 );

    /* Funcionario #1 */
    strcpy( f.vetor[0].nome, "Fulano" ); 
    f.vetor[0].salario = 1000.00;

    /* Funcionario #2 */
    strcpy( f.vetor[1].nome, "Ciclano" ); 
    f.vetor[1].salario = 1200.00;

    /* Funcionario #3 */
    strcpy( f.vetor[2].nome, "Beltrano" ); 
    f.vetor[2].salario = 1500.00;

    /* Exibe lista de Funcionarios da Firma */
    for( i = 0; i < f.qtdFuncionario; i++ )
    {
        printf("Funcionario #%d:\n", i+1 );
        printf("\tNome: %s\n", f.vetor[i].nome );
        printf("\tSalario: %.2f\n", f.vetor[i].salario );
    }

    /* Libera memoria */
    free(f.vetor);

    return 0;
}

Exit:

Funcionario #1:
    Nome: Fulano
    Salario: 1000.00
Funcionario #2:
    Nome: Ciclano
    Salario: 1200.00
Funcionario #3:
    Nome: Beltrano
    Salario: 1500.00

0

The type of vetor is Funcionario* and not Funcionario**. So to get a Funcionario (and not a Funcionario*), you use vetor[blablabla]. As the result of this is a Funcionario (and not a Funcionario*), to access the field nome, you use .

Being vetor a pointer, when you use the [] on a pointer, will result in the type of the pointer component (ie, Funcionario). Like Funcionario is not a pointer, members must be accessed with . and not with ->. If you got one Funcionario*, then I would use ->, which is valid only for pointers.

As to precedence:

  • What is inside the [] is solved first, ie the firma->qtdFuncionario, that will result in some number.

  • Then the [] is applied to the pointer, which then obtains an element whose address will be calculated by the appropriate code the compiler enters. Note that what is obtained is an element, not a pointer. This solves the expression on the left side of the . or ->.

  • Having the contents on the left side of the . or -> been fully resolved, then what’s on the right side can be solved. If what’s on the left side is a pointer, use ->. Otherwise it is used ..

How did you not use the dereference operator (the * unary) in the expression, his precedence ends up being irrelevant. His mistake lies in believing that the underexpression with the [] should result in a pointer, which is not true.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.