[Linuxtrent] Re: warning: assignment from incompatible pointer type [enabled by default]

  • From: Lele Gaifax <lelegaifax@xxxxxxxxx>
  • To: linuxtrent@xxxxxxxxxxxxx
  • Date: Mon, 19 Mar 2012 19:44:49 +0100

Il giorno Mon, 19 Mar 2012 11:52:34 +0100
Pietro <peter.zamb@xxxxxxxxx> ha scritto:

> Ciao a tutti,
> 
> scusate l'off-topic, sto provando a scrivere un programma in C... ma
> ho appena iniziato e sto sicuramente facendo degli errori banali...
> c'è qualcuno qui in lista che riesce a capire perché gcc protesta?
> 
> $ gcc -c l.c
> l.c: In function ‘add_elem_to_list’:
> l.c:34:19: warning: assignment from incompatible pointer type [enabled
> by default]
> l.c:36:13: warning: assignment from incompatible pointer type [enabled
> by default]

L'errore specifico te l'hanno già spiegato: hai “preso” l'indirizzo di
un elemento, quando quell'elemento era già un indirizzo...

Ma un problema ancora più subdolo nella tua implementazione è relativo
all'uso della cosidetta “memoria automatica” del C, in altre parole la
memoria che ogni funziona alloca nello stack per far posto alle
variabili che vi dichiari: questa memoria viene riutilizzata
automaticamente mano a mano che le funzioni terminano... non la puoi
quindi sfruttare come hai fatto tu, “dichiarando” un certo elemento e
inserendolo in una lista di puntatori, come fai in questo snippet:

>     for ( i = 0; i < nelements; i++ )
>     {
>         elem elem1 = {{i,0}, NULL};
>         add_elem_to_list(&elem1, &list0);
>     }

che nella migliore delle ipotesi non fa altro che “agganciare” alla
lista il medesimo indirizzo di memoria, causando un bel casino :-)

In allegato una veloce revisione del programmillo, dove ho usato
la funzione standard “malloc(size)” che alloca una porzione di memoria
della dimensione richiesta, che poi viene usata per inserirci i valori
associati a ciascun elemento che infine viene “legato” alla catena che
rappresenta la lista: questo è il modo tradizionale per far crescere
dinamicamente una struttura C, e richiede un altrettanto esplicito
“free()” di ciascun pezzetto quando la struttura non è più utile, ma
che ti lascio come ulteriore esercizio.

ciao, lele.
#include <stdlib.h>
#include <stdio.h>

// point
typedef struct _pnt_
{
  int row;
  int col;
} pnt;


// element
typedef struct _elem_
{
  pnt point;
  struct _elem_ *next;
} elem;

// list of element
typedef struct _list_
{
  elem *first;
  elem *last;
  int length;
} list;

void
add_point_to_list(int row, int col, list *l)
{
  elem *e = malloc(sizeof(elem));

  e->point.row = row;
  e->point.col = col;
  e->next = NULL;

  // set the first point if list is empty, otherwise
  // update the link from the last element to new point
  if (l->length == 0)
    l->first = e;
  else
    l->last->next = e;

  // update the last in the list
  l->last = e;

  // update the length attribute
  l->length += 1;
}

void
populate(int nrows, list *l)
{
  int row;
  for (row = 0; row < nrows; row++)
    add_point_to_list(row, 0, l);
}

list *
create_empty_list()
{
  list *l = malloc(sizeof(list));
  l->length = 0;
  l->first = l->last = NULL;
  return l;
}

void
print_list(list *l)
{
  int i;
  elem *e;

  for (i = 0, e = l->first; i < l->length; i++)
    {
      printf("%d) row=%d col=%d\n", i, e->point.row, e->point.col);
      e = e->next;
    }
}

int
main()
{
  list *l = create_empty_list();
  populate(10, l);
  print_list(l);
  return 0;
}

Other related posts: