0

Hello I'm dooing a program in c with linked lists and I don't know what i`m doing wrong. The problem is on the line: "podio novo = (struct podio) malloc(sizeof(podio));" inside of push. here is my code:

struct Sucesso {
    char nome_equipe[N1];
    float distancia_alvo;
    float tempo_propulsao;
};

struct Node {
    struct Sucesso *dados;
    struct Node *prox;
};

typedef struct Node podio;

void push(podio *p, struct Sucesso elem) {
    podio *novo = (struct podio*) malloc(sizeof(podio));
    if(novo != NULL) {
        novo->dados=elem;
        novo->prox=*p;
        *p=novo;
    } 
}
  • "The problem is on the line" And whats the problem? – tkausl Oct 04 '16 at 03:38
  • on xcode it says: Incompatible pointer types initializing 'podio *'(aka 'struct Node*') with an expression of type 'struct podio *' – Marco Aurlio Moreira dos Anjos Oct 04 '16 at 03:39
  • [No need to cast return value of malloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – smac89 Oct 04 '16 at 05:20
  • @smac89 You need to cast value returned my malloc as it returns generic pointer which needs to be casted into the required pointer on which we are performing operations like accessing. – CocoCrisp Oct 04 '16 at 05:24

2 Answers2

2

The problem is that struct podio is an incomplete type unrelated to the type podio (aka struct Node) defined via typedef struct Node podio;. Therefore, the two types (podio * and struct podio *) are incompatible; they point to different types of object.

If you lose the struct in the malloc() line, your code should compile.

podio *novo = (podio *) malloc(sizeof(podio));

or:

podio *novo = malloc(sizeof(*novo));

There'll be those who castigate you for casting the result of malloc(); fortunately for you, I'm not one of them.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • It's just a curiosity to ask, not cross questioning you :) – CocoCrisp Oct 04 '16 at 05:28
  • I've added a link to the canonical Q&A on the subject of casting `malloc()`. When I was learning C, the cast was crucial, especially on the machines I learned on. Back in those days, `malloc()` returned a `char *` — there wasn't yet a `void *` type — and on the machines I learned on, the `char *` address for a piece of memory was quite different from an 'anything else `*`' address to the same memory. High order bits in the address indicated that it was a `char *` instead of, for example, an `int *` address. If you didn't declare `malloc()` correctly, or if you didn't cast the result, crash! – Jonathan Leffler Oct 04 '16 at 05:32
  • These days, the cast isn't strictly necessary. The main claim is that it can hide the fact that you forgot to include `` to declare `malloc()`. I don't compile with options that allow that — it would be an error not to declare `malloc()` — so I don't regard it as a problem, and I tend towards consistency with my original learning. In C++, the rules are different. The cast is mandatory. If there's any pretense that the code can be compiled by a C++ compiler, the cast is necessary. However, good C++ code does not use `malloc()`, so that's more than a little debatable. – Jonathan Leffler Oct 04 '16 at 05:34
  • Correct, C++ mainly uses new keyword to allocate dynamic memory or heap memory. – CocoCrisp Oct 04 '16 at 05:35
  • The machines on which I learned don't exist any more either; I'm not sure how they'd handle Standard C's requirements. Maybe the compiler would have to do implicit casting. However, you're right; since 1989 (years after I learned C), the return type of `malloc()` is `void *`. There isn't a need to cast `void *` to another type according to the standard. So, the argument goes, you should not include the cast. Omitting it cuts down on the repetitions of the type name in the line. Your judgement call — don't expect me to cast stones at those who use a cast. – Jonathan Leffler Oct 04 '16 at 05:39
  • In strict C code, I use the cast for portability. What I mean by portability is portable for older versions of the c standard where void*'s dont get promoted. I quote from K&R's "The C Programming Language": "In C, the proper method is to declare that malloc returns a pointer to void, then explicitly coerce the pointer into the desired type with a cast." The reason that I impose such a requirement is that you dont always have a choice of what compiler you can use – CocoCrisp Oct 04 '16 at 05:43
  • It's only pre-standard C that could be a problem, and that would require a compiler and platform that's more than a quarter century old. Such platforms do exist, but they're few and far between, and there's usually a (more or less) standard-compliant compiler available too. You have to make your own decision. I still tend to do the cast, but not always. – Jonathan Leffler Oct 04 '16 at 05:47
0

Problem is with these lines

novo->dados=elem;
novo->prox=*p;

Here novo->dados is struct Sucesso* but elem is struct Sucesso ie not a pointer. So you are assigning structure to a structure pointer which is not valid. You need to pass address of in elem in push().

And nove->prox is struct Node * but *p is podio *p aka struct Node *, so *p is padio not a pointer. So again you are assigning structure to pointer to structure.

tkausl
  • 13,686
  • 2
  • 33
  • 50
Rohan
  • 52,392
  • 12
  • 90
  • 87
  • void push(podio *p, struct Sucesso elem) { podio *novo = (struct Node *) malloc(sizeof(novo)); if(novo != NULL) { novo->dados=&elem; novo->prox=p; *p = *novo; } } It seems to be working, what do you think? – Marco Aurlio Moreira dos Anjos Oct 04 '16 at 04:26
  • `&elem` gives you address of variable on stack, which may not hold appropriate contents once function completes. So you should not use it that way. – Rohan Oct 04 '16 at 05:16