Pointers and data type hidden in C

Asked

Viewed 208 times

0

EDIT: I’ll leave the codes right below in text same.

Good evening. Please see attached image.

It is the implementation of a function whose prototype is defined in another file named "stack. h". As it stands, it works perfectly.

However, if I delete line 11 and modify line 5 to typedef struct { .... } stack; i have a compilation error:

pile. c: In Function 'breed:

stack. c:15:6: error: Dereferencing Pointer to incomplete type ːstruct pile'

 p->v = malloc(tamanho * sizeof(char));
  ^~

Could someone help me understand this mistake?

From now on, thank you!

Arquivo "pilha.c"

--------------- pile. h -----------------

typedef struct pilha *Pilha;

Pilha criaPilha(int tamanho);

int pilhaCheia(Pilha p);

int pilhaVazia(Pilha p);

void empilha(Pilha p, char elemento);

char desempilha(Pilha p);

int topo(Pilha p);

char eleTopo(Pilha p);

----------- pile. c -----------

#include <stdio.h>
#include <stdlib.h>
#include "pilha.h"

struct pilha {
    char *v;
    int topo;
    int tamanho;
};

typedef struct pilha pilha;

Pilha criaPilha(int tamanho) {
    Pilha p = malloc(sizeof(pilha));
    p->v = malloc(tamanho * sizeof(char));
    p->topo = 0;
    p->tamanho = tamanho;

    return p;
}

int pilhaCheia(Pilha p) {
    if (p->topo > p->tamanho)
        return 1;
    return 0;
}

int pilhaVazia(Pilha p) {
    if (p->topo == 0)
        return 1;
    return 0;
}

void empilha(Pilha p, char elemento) {
    if (!pilhaCheia(p)) {
        p->topo++;
        p->v[p->topo] = elemento;
    }
    else
        printf("Pilha cheia!\n");
}

char desempilha(Pilha p) {
    if (!pilhaVazia(p)) {
        p->topo--;
        return p->v[p->topo + 1];
    }
    else
        return '\0';
}

int topo(Pilha p) {
    return p->topo;
}

char eleTopo(Pilha p) {
    return p->v[p->topo];
}
  • Put the code in text to make it easier for us, and the .h.

  • I left the codes in the post Edit.

  • I was going to copy and paste your code to change and make an answer, but as picture gets difficult.

  • Hi, @Victorstafusa. I edited the post and left the codes in the comments.

1 answer

1

typedef struct Pilha {
    char *v;
    int topo;
    int tamanho;
} Pilha;

Pilha *criaPilha(int tamanho) {
    Pilha *p = (Pilha *) malloc(sizeof(Pilha));
    p->v = (char *) malloc(tamanho);
    p->topo = 0;
    p->tamanho = tamanho;
    return p;
}

There are some things here to be observed:

  1. You mustn’t confuse pilha with Pilha. Remember that C is case sensitive. Have Pilha and pilha how different things it is to ask to do lambança.

  2. The function malloc always returns a pointer. So don’t forget the * on the pointer.

  3. Note the strange syntax of typedef. She says the nickname given to struct Pilha {...} is Pilha.

  4. Place Casts in the malloc is a good idea. The reason for this is that there are some interoperability problems between C and C++ if you don’t do this.

  5. The standard C language says that sizeof(char) always is 1, regardless of the platform it is. Therefore, you do not need to multiply by sizeof(char) within the malloc.

  6. Hide that a data type is a pointer by means of a typedef is another way to ask to make lambança.

  7. In the header file pilha.h, you would only use typedef struct Pilha Pilha;, while putting the struct complete in pilha.c.

  • Hi, Victor. So: #1. Stack (uppercase) is a type of data the client would use, while stack (lowercase) is just the implementation of functions that would not be visible to the client. So it was left on purpose. #2. In the stack file. h was there is a line "typedef struct stack *Stack", ie when I invoke Stack automatically I am referring to the pointer for struct stack, so I didn’t use *. #3. Idem #1 and #2 #4. Interesting information! #5. Very well noted! I passed that unnoticed kk Thanks for the comments and information

  • @Lucaslopes I edited the answer to address these points that you raised.

  • I get it. Actually #6 is something that creates confusion. I just used it to try to "understand how it works". Apparently it’s not even remotely good programming practice. Thanks again!

  • 1

    Both #3 and #4 are very common to use in C. Regarding malloc not lead cast is because the syntax becomes much less verbose and simpler to keep valid if it changes the type of pointer, among other things, as is debated in this post. In addition, it is highly unlikely that mallocs are wanted in c++ since c++ has much better ways of declaring memory and is validated in relation to the type, such as the operator new.

  • @Isac I know what to wear malloc in C++ is not considered one of the best practices, but I’ve seen it happen a few times even without a block extern "C" {...}, and I’ve seen questions here at Sopt where it caused confusion. Including, new is not considered more good practice in C++. As for #3, I say the syntax is strange because for beginners it seems very confusing (and let’s face it, it would be more intuitive to have the nickname before the type being nicknamed rather than after).

Browser other questions tagged

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