Home > Blockchain >  Code is printing pointer address (I think) instead of value?
Code is printing pointer address (I think) instead of value?

Time:04-11

I have a list defined as

typedef struct node {
    Voo *voo;
    ListaReservas nodeReservas; /* Ignore this */
    struct node *next;
} *Node;

I created some functions to help me add or remove nodes from the list like:

/* creates a node */
Node criaNode(Voo v) {
    Node new = (Node)malloc(sizeof(struct node));
    new->voo = &v; 
    /* I had new->voo = v; but vscode told me it was wrong so i changed it to &v */
    new->next = NULL;
    return new;
}

Voo is defined as:

typedef struct {
    int dia;
    int mes;
    int ano;
} Data;

typedef struct {
    int horas;
    int minutos;
} Tempo;

typedef struct {
    char codigo[LEN_CODIGO   1];
    char partidaID[LEN_ID   1];
    char chegadaID[LEN_ID   1];
    Data datapartida;
    Tempo horapartida;
    Tempo duracao;
    Data datachegada;
    Tempo horachegada;
    int capacidade;
} Voo;

Now I wanted to iterate through the list and print its values as such

Voo *v;
for (n = headVoos; n != NULL; n = n->next) {
    v = n->voo;                         
    printf("%s %s %s %.2d-%.2d-%d %.2d:%.2d\n",
           v->codigo, v->partidaID, v->chegadaID,
           v->datapartida.dia, v->datapartida.mes, v->datapartida.ano, 
           v->horapartida.horas, v->horapartida.minutos);
}

The program is not printing correctly. For example where it should appear

AA1 AAA AAD 16-03-2022 14:50

its appearing instead

� 146187376-32765--1940381952 40355300:50

What's causing this and how can I avoid it in the future?

EDIT After replacing in the struct node the Voo *voo definition by Voo voo, I am now getting an error in one of the auxiliary functions:

/* deletes node */
Node eliminaNode(Node head, Voo v)
{
    Node n, prev;
    for (n = head, prev = NULL; n != NULL; prev = n, n = n->next)
    {
        if (n->voo == v) /* expression must have arithmetic or pointer error */
        {
            if (n == head)
                head = n->next;
            else
                prev->next = n->next;
            free(n->next);
            free(n);
            break;
        }
    }
    return head;
}

CodePudding user response:

In criaNode you're taking the address of the parameter v and returning it from the function via a pointer to dynamic memory. That address is no longer valid after the function returns. Subsequently dereferencing that invalid address then triggers undefined behavior.

It probably makes more sense for struct node to contain a Voo directly instead of a pointer to one. So change the member to a non-pointer:

Voo voo;

And assign the parameter directly:

new->voo = v; 

CodePudding user response:

There are multiple problems here:

  • there seems to be a confusion between structures and pointers to structures. In C, you must understand the difference between manipulating objects (allocating as local objects or from the head, passing as arguments or returning as values) and pointers to objects, which are a more idiomatic as arguments to functions and allow functions to modify the object they point to.

  • the confusion is amplified by a very error prone construction: hiding pointers behind typedefs. Do not do that, define object types for the actual structure, using the same or a different name as the struct tag, and make all pointers explicit with the * syntax.

  • you pass an actual Voo object as an argument and allocate a list node using the address of this argument. This is incorrect because the argument will be discarded as soon as the function returns, makeing the list point to invalid memory and explaining the weird output you observe.

  • Node eliminaNode(Node head, Voo v) should take a pointer to the head node and return a success indicator. It should take a Voo * argument and it should not free(n->next) because the next node is still in use after the removal.

Here is a modified version:

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

#define LEN_CODIGO  30
#define LEN_ID      30

typedef struct Data {
    int dia;
    int mes;
    int ano;
} Data;

typedef struct Tempo {
    int horas;
    int minutos;
} Tempo;

typedef struct Voo {
    char codigo[LEN_CODIGO  1];
    char partidaID[LEN_ID   1];
    char chegadaID[LEN_ID   1];
    Data datapartida;
    Tempo horapartida;
    Tempo duracao;
    Data datachegada;
    Tempo horachegada;
    int capacidade;
} Voo;

typedef struct Node {
    struct Voo *voo;
    //ListaReservas nodeReservas; /* Ignore this */
    struct Node *next;
} Node;

/* creates a node */
Node *criaNode(Voo *v) {
    /* allocation with calloc is safer as the object will be initialized to 0 */
    Node *nodep = calloc(1, sizeof(*new));
    if (nodep) {
        nodep->voo = v; 
        nodep->next = NULL;
    }
    return nodep;
}

/* deletes node */
int eliminaNode(Node **head, Voo *v) {
    for (Node *n = *head, *prev = NULL; n != NULL; prev = n, n = n->next) {
        if (n->voo == v) {
            if (n == *head)
                *head = n->next;
            else
                prev->next = n->next;
            free(n);
            return 1;  /* article was found and freed */
        }
    }
    return 0;  /* article was not found */
}

void printList(const Node *head) {
    for (const Node *n = head; n != NULL; n = n->next) {
        const Voo *v = n->voo;                         
        printf("%s %s %s %.2d-%.2d-%.2d %.2d:%.2d\n",
               v->codigo, v->partidaID, v->chegadaID,
               v->datapartida.dia, v->datapartida.mes, v->datapartida.ano, 
               v->horapartida.horas, v->horapartida.minutos);
    }
}
  • Related