2012-02-15 27 views
8

Non sono un esperto di linguaggi di programmazione di livello inferiore non orientato agli oggetti e sono nel mezzo della scrittura di un codice C per un progetto al lavoro. Sto cercando di creare alcuni tipi di dati astratti decenti con cui lavorare, e Googling mi ha fatto capire che le persone usano gli ADT basati su struct in due modi. Alcune persone definiscono un tipo di dati come struct:Quando dovrei typedef struct vs. pointer to struct?

typedef struct adt { 
    //content here 
} adt; 

ed espongono al mondo nel file di intestazione.

Altri definiscono un tipo di dati come puntatorea struct:

// In .c file: 
typedef struct adt_s { 
    //content here 
} adt_s, *adt; 


// In .h file: 
typedef struct adt_s *adt; 

Capisco che questo approccio consente di typedef una struttura senza dare al mondo esterno alcuna conoscenza di ciò che è dentro questa struct, quindi i programmatori può solo utilizzare le funzioni fornite nello stesso file di intestazione per operare su questo tipo di dati.

Ci sono altri motivi per scegliere l'altro? Esiste una "regola generale" generale per quando definiscono gli ADT come strutture e quando li definiamo come indicatori delle strutture?

risposta

6

È possibile inoltrare dichiarare una struct senza typedef troppo - le uniche distinzioni sono:

  • se l'interfaccia sembra più pulito, con o senza la parola chiave struct
  • se l'interfaccia sembra più pulito, con o senza il puntatore esplicito *

Es.

struct S1; 
typedef struct S2 S2; 
typedef struct S3_s *S3; 

void foo1(struct S1 *arg); 
void foo2(S2 *arg); 
void foo3(S3); 

Ovviamente ciò vale solo per le strutture dichiarate in avanti in un'intestazione di interfaccia.

Se non si nasconde l'implementazione della struttura in primo luogo, la scelta tra S1 e S2 è una questione di preferenza (o coerenza). Non userei S3 a meno che non sia un tipo veramente opaco/nascosto.

La preferenza personale sarebbe quella di utilizzare S1 (parola chiave struct esplicita) per aggregati grandi/complessi e S2 per le piccole strutture che potrebbero essere considerate come valori e non sempre passare per puntatore. YMMV.

+0

Per scopi di leggibilità forse è meglio scrivere 'typedef struct S3_s * S3' invece di' typedef struct S3_s * S3', no? – Eregrith

+0

@Eregrith: se si usa la semantica del linguaggio formale, 'typedef struct S3_s * S3' dice che il dichiaratore' * S3' ha tipo 'struct S3_s' e la classe di memoria' typedef', quindi mettere l'asterisco con l'identificatore è effettivamente idiomatico ; tuttavia, mettere l'asterisco con il tipo è più in sintonia con quante (la maggior parte?) le persone pensano alle dichiarazioni; per quanto mi riguarda, entrambe le versioni vanno bene finché sei coerente ... – Christoph

+0

Ho appena selezionato quella spaziatura per coerenza con l'OP, dal momento che posso vedere i benefici in entrambi i modi. – Useless

1

La decisione di nascondere o non nascondere si basa interamente su di te come designer del tuo catalogo. Se si desidera riservare il diritto di modificare il proprio struct in futuro, non si dovrebbe esporre nessuno dei suoi membri al "mondo". Se si fornisce un struct come mezzo per comunicare con la libreria in primo luogo (ad esempio, un struct che rappresenta un punto in 3D), non è possibile nascondere i suoi membri dal mondo, in quanto ciò vanificherebbe lo scopo.

1

leggere le Linus Torvalds post Capitolo 5: typedef