2010-07-19 3 views
12

Y a-t-il un avantage à avoir des structures jamais définies dans C?Structure jamais définie

Exemple dans le code source SQLite:

/* struct sqlite3_stmt is never defined */ 
typedef struct sqlite3_stmt sqlite3_stmt; 

Et l'objet est manipulé comme ceci:

typedef struct Vdbe Vdbe; 
struct Vdbe { 
    /* lots of members */ 
}; 


int sqlite3_step(sqlite3_stmt *pStmt) { 
    Vdbe *v = (Vdbe*) pStmt; 
    /* do stuff with v... */ 
} 

Alors, pourquoi ne pas simplement utiliser un type abstrait d'habitude, avec la structure réelle privée définie dans foo.c source et un public typedef en foo.h en-tête?

+1

Il n'y a pas de bonne raison. Mais beaucoup de gens font beaucoup de choses stupides en C, même dans de grands projets bien connus. –

+7

À R .: Vous n'irez pas très loin avec ce genre d'attitude dédaigneuse. sqlite est un projet mature bien connu qui est réputé pour sa qualité. Il est probable que D. Richard Hipp sait ce qu'il fait avec le code. –

Répondre

9

Pour clarifier: Qu'est-ce que vous vous demandez pourquoi SQLite fait ce qui précède au lieu de le faire:

fichier d'en-tête:

typedef struct sqlite3_stmt sqlite3_stmt; 

fichier C:

struct sqlite3_stmt { 
    /* lots of members */ 
}; 


int sqlite3_step(sqlite3_stmt *pStmt) { 
    /* do stuff with pStmt... */ 
} 

(C'est la forme canonique du motif "pointeur opaque" lié à la réponse de KennyTM.)

Le seul bon raison pour laquelle je peux penser à ce que fait SQLite ce qu'il fait est le suivant:

Le code backend, je spécule, est venu avant l'API et a utilisé le nom Vdbe - le nom signifie probablement quelque chose lié à la mise en œuvre le long de la lignes de "l'entrée de la base de données virtuelle" (deviner sauvagement ici). Quand le temps est venu de créer l'API, quelqu'un s'est rendu compte que le paramètre requis par sqlite3_step était un Vdbe mais que ce n'était pas exactement un nom qui aurait beaucoup de sens pour l'utilisateur de l'API. Par conséquent, du point de vue de l'utilisateur, un Vdbe est appelé sqlite3_stmt.

Le point ici est donc de faire la différence entre deux vues du même élément: Le backend pense en termes de Vdbe s (quels qu'ils soient) parce que ce nom qui fait sens dans le contexte de la mise en œuvre. L'API parle de sqlite3_stmt s parce que c'est un nom qui a du sens dans le contexte de l'interface . Edit: Comme le souligne Amarghosh, pourquoi ne pas le faire pour obtenir le même résultat?

typedef struct Vdbe sqlite3_stmt; 

KennyTM points out a good possible reason (s'il vous plaît le vote, je ne veux pas siphonner son représentant ici): VDBE est seulement l'un de plusieurs backends possibles; l'interface utilise un "générique" sqlite3_stmt, et il est ensuite converti à tout ce que le backend utilise pour l'implémenter.

+4

Alors pourquoi ne pas simplement 'typedef struct Vdbe sqlite3_stmt; ' – Amarghosh

+0

Vous avez raison, c'est ce que je demandais. J'aime l'idée des deux vues du même objet. (et, d'ailleurs, c'est ma compréhension de SQLite que VDBE signifie "moteur de base de données virtuel") – Axel

+0

@Amarghosh: Bon point ... La réponse éditée de KennyTM fournit une bonne raison possible (que VDBE est juste un de plusieurs backends) –

15

Il est défini comme ceci pour masquer les détails d'implémentation de sqlite3_stmt de l'utilisateur, évitant ainsi que les états internes ne soient perturbés. Voir Opaque pointer.

(Cela oblige également à l'utilisateur d'utiliser uniquement le type en tant que pointeur puisque la structure sqlite3_stmt a lui-même mise en œuvre incomplète.)


Edit: VDBE (moteur de base de données virtuelle) est juste "un" back fin de l'API SQLite3. Je crois que le back-end est modifiable, donc sqlite3_stmt* n'est pas nécessairement un Vdbe*. N'exposant pas Vdbe* dans l'API, car les détails du back-end ne doivent pas être exposés.

+2

Néanmoins, dans l'exemple de l'article de pointeur Opaque, le 'struct cat_t' est défini ... Est-ce que' struct sqlite3_stmt' est seulement utilisé pour cacher l'implémentation sur 'struct Vdbe'? Alors, y a-t-il une raison de ne pas utiliser le motif de pointeur Opaque sur 'Vdbe'? – Axel

+0

+1 "Je crois que le back-end est modifiable" semble être une raison très plausible! –

Questions connexes