[C] Struct incomplete: un mistero.

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Avatar utente
Blallo
Packager
Packager
Messaggi: 3284
Iscritto il: ven ott 12, 2007 11:37
Nome Cognome: Savino Liguori
Slackware: 14.2 / 12.2
Kernel: 4.4.14-smp
Desktop: DWM
Località: Torino / Torremaggiore (FG)
Contatta:

[C] Struct incomplete: un mistero.

Messaggioda Blallo » sab giu 21, 2014 23:43

Premetto che si tratta solo di una richiesta di spiegazioni, il programma per fortuna funziona perfettamente.

Ho un dubbio che mi attanaglia la mente sulle struct incomplete.
Praticamente ho creato un ADT FIFO costituito da oggetti Item, anch'essi astratti.
(Item è composto da una stringa e un intero).

Non capisco come si faccia a risolvere un problema di "tipo incompleto".
Nel file item.c c'è questo pezzo di codice suggeritomi da un amico:

Codice: Seleziona tutto

 i = (Item) malloc (sizeof(*i));

che io in precedenza avevo scritto come

Codice: Seleziona tutto

 i = (Item *) malloc (sizeof(Item));

Nella mia versione mi dava come errore "incomplete type error", che con la prima versione non si presenta.
Il punto è che... non capisco il senso della malloc di cui sopra.
Anche perché nella fifo questa malloc

Codice: Seleziona tutto

 queue = (Queue *) malloc (sizeof(Queue));

funziona egregiamente.
Il mio amico non è stato in grado di farmi capire niente, probabilmente ha solo copincollato da qualche sorgente.
Qualcuno sa darmi una spiegazione? :)

Allego sotto i listati.
Grazie in anticipo!

item.h

Codice: Seleziona tutto

#ifndef ITEM_H_INCLUDED
#define ITEM_H_INCLUDED

#define MAXBUF 100
#define MAXSTRING 20

#define FAILURE 0
#define SUCCESS 1

typedef struct ItemStruct *Item;

Item ItemGet();
void printItem (Item item, FILE *fp);

#endif // ITEM_H_INCLUDED

item.c

Codice: Seleziona tutto

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

#include "item.h"


struct ItemStruct
{
    char word[MAXSTRING];
    int number;
};

Item ItemGet()
{
    Item i;
    char buf[MAXBUF];

    i = (Item) malloc (sizeof(*i));
    if (i == NULL)
    {
        fprintf ( stderr, "Error: insufficient memory for new element.\n");
        return NULL;
    }

    fgets(buf, MAXBUF, stdin);
    sscanf(buf, "%s %d", i->word, &i->number);

    return i;
}


void printItem (Item item, FILE *fp)
{
    fprintf(fp, "%s %d\n", item->word, item->number);
}


fifo.h

Codice: Seleziona tutto

#ifndef FIFO_H_INCLUDED
#define FIFO_H_INCLUDED

#include "item.h"

typedef struct QueueStruct Queue;

Queue *QueueInit(int size);
int QueueEmpty(Queue *queue);
void QueuePut(Queue *queue, Item item);
Item QueuePush(Queue *queue);

void QueuePrint(Queue *queue, FILE *fp);
void QueueFree(Queue *queue);

#endif // FIFO_H_INCLUDED

fifo.c

Codice: Seleziona tutto

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


struct QueueStruct
{
    Item *q;
    int N;
    int head;
    int tail;
};

/*
 * QueueInit (int size)
 *
 * Create a queue of size [Size+1].
 *
 */
Queue *QueueInit(int size)
{
    Queue *queue;

    queue = (Queue *) malloc (sizeof(Queue));
    if (queue == NULL)
    {
        fprintf ( stderr, "Error: insufficient memory for new element.\n");
        return NULL;
    }

    queue->q = (Item *) malloc (sizeof(Item) * (size+1));
    if(queue == NULL)
    {
        fprintf ( stderr, "Error: insufficient memory for new queue.\n");
        free(queue);
        return NULL;
    }
    queue->N = size+1;
    queue->head = queue->N;
    queue->tail = 0;

    return queue;
}

/*
 * QueueEmpty()
 *
 * Checks if the queue is Empty.
 *
 */
int QueueEmpty(Queue *queue)
{
    return queue->head % queue->N == queue->tail;
}

void QueuePut(Queue *queue, Item item)
{
    if ( (queue->tail + 1) != queue->head)
    {
        queue->q[queue->tail++] = item;
        queue->tail = queue->tail % queue->N;
    }
    else
        fprintf(stdout, "Full queue! Data not inserted.\n");
}

Item QueuePush(Queue *queue)
{
    queue->head = queue->head % queue->N;
    return queue->q[queue->head++];
}

void QueuePrint(Queue *queue, FILE *fp)
{
    int i;

    for(i=queue->head % queue->N; i !=queue->tail; i++)
        printItem (queue->q[i], fp);
}

void QueueFree(Queue *queue)
{
    int i;

    for(i=queue->head % queue->N; i !=queue->tail; i++)
        free(queue->q[i]);
    free(queue->q);
    free(queue);
}
My DWM configuration: https://github.com/8lall0/dwm

Feel free to use.

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6389
Iscritto il: gio nov 03, 2005 14:05
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: [C] Struct incomplete: un mistero.

Messaggioda targzeta » dom giu 22, 2014 0:34

L'errore parte dalla typedef. Quella corretta è:

Codice: Seleziona tutto

typedef struct QueueStruct Queue;
mentre in item hai (nota l'* di troppo):

Codice: Seleziona tutto

typedef struct ItemStruct *Item;
Tutto segue in cascata (a me le typedef non piacciono molto).

Emanuele
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà 

Avatar utente
Blallo
Packager
Packager
Messaggi: 3284
Iscritto il: ven ott 12, 2007 11:37
Nome Cognome: Savino Liguori
Slackware: 14.2 / 12.2
Kernel: 4.4.14-smp
Desktop: DWM
Località: Torino / Torremaggiore (FG)
Contatta:

Re: [C] Struct incomplete: un mistero.

Messaggioda Blallo » dom giu 22, 2014 4:15

Stesso errore.
Nel momento in cui la alloco nella fifo:

Codice: Seleziona tutto

queue->q = (Item *) malloc (sizeof(Item) * (size+1));

mi sputa fuori questo:

Codice: Seleziona tutto

error: invalid application of 'sizeof' to incomplete type 'Item'
My DWM configuration: https://github.com/8lall0/dwm

Feel free to use.

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6389
Iscritto il: gio nov 03, 2005 14:05
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: [C] Struct incomplete: un mistero.

Messaggioda targzeta » dom giu 22, 2014 11:03

Quello è normale. Hai definito la struttura in item.c ma in fifo.c hai incluso item.h. Devi fare qualcosa tipo:

item.h

Codice: Seleziona tutto

#ifndef ITEM_H_INCLUDED
#define ITEM_H_INCLUDED

#define MAXBUF 100
#define MAXSTRING 20

#define FAILURE 0
#define SUCCESS 1

typedef struct ItemStruct
{
  char word[MAXSTRING];
  int number;
} Item;

Item *ItemGet();
void printItem (Item *item, FILE *fp);

#endif // ITEM_H_INCLUDED
Emanuele
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà 

Avatar utente
Blallo
Packager
Packager
Messaggi: 3284
Iscritto il: ven ott 12, 2007 11:37
Nome Cognome: Savino Liguori
Slackware: 14.2 / 12.2
Kernel: 4.4.14-smp
Desktop: DWM
Località: Torino / Torremaggiore (FG)
Contatta:

Re: [C] Struct incomplete: un mistero.

Messaggioda Blallo » dom giu 22, 2014 12:39

Però io volevo provare a fare qualcosa di questo tipo.
http://ejrh.wordpress.com/2011/04/29/en ... tion-in-c/
(Alla sezione Data Hiding)
Volevo, insomma, provare ad incapsulare la struttura, per dirla alla Java. :)
My DWM configuration: https://github.com/8lall0/dwm

Feel free to use.

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6389
Iscritto il: gio nov 03, 2005 14:05
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: [C] Struct incomplete: un mistero.

Messaggioda targzeta » dom giu 22, 2014 15:52

Potevi dirlo prima.

Quello che fa lui è corretto, però allora tu non puoi mai riferire a Item direttamente fuori dal file item.c, devi:
  • usare sempre un puntatore;
  • usare solo i metodi dichiarati dentro item.h;
In particolare per allocare la coda devi fare:

Codice: Seleziona tutto

 queue->q = (Item **) malloc(sizeof(Item *) * size);
(quidi q nella QueueStruct diventa Item **q. Una volta allocato queue->q però devi anche allocare i vari oggetti Item (q->[0], q->[1], ...) usando la ItemGet().

Poi ritorni sempre e solo oggetti (Item *) e se vuoi manipolarne il contenuto devi aggiungere funzioni a item.{c,h} tipo:

Codice: Seleziona tutto

void setWord(Item *, char*);
setNumber(Item*, int);
char *GetWord(Item *);
int GetNumber(Item *);


Il punto è che solo il file item.c può accedere alla struttura Item correttamente, perché solo lui sa com'è fatta. Questa è la programmazione ad oggetti in C che a me piace molto,
Emanuele
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà 


Torna a “Programmazione”

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite