c coding-style struct typedef opaque-pointers

Estructuras O opacas: ¿cómo deberían declararse?



coding-style typedef (2)

Mi voto es para la tercera opción que mouviciel publicó y eliminó:

He visto una tercera forma:

// foo.h struct foo; void doStuff(struct foo *f); // foo.c struct foo { int x; int y; };

Si realmente no puede soportar escribir la palabra clave struct , typedef struct foo foo; (nota: deshacerse del subrayado inútil y problemático) es aceptable. Pero haga lo que haga, nunca use typedef para definir nombres para tipos de punteros. Oculta la información extremadamente importante de que las variables de este tipo hacen referencia a un objeto que podría modificarse cada vez que las pasas a funciones, y hace que lidiar con versiones del puntero con calificaciones diferentes (por ejemplo, const -qualified) sea un gran dolor .

He visto los dos estilos siguientes de declarar tipos opacos en las API de C. ¿Hay alguna ventaja clara al usar un estilo sobre el otro?

Opción 1

// foo.h typedef struct foo * fooRef; void doStuff(fooRef f); // foo.c struct foo { int x; int y; };

opcion 2

// foo.h typedef struct _foo foo; void doStuff(foo *f); // foo.c struct _foo { int x; int y; };


bar(const fooRef) declara una dirección inmutable como argumento. bar(const foo *) declara una dirección de un foo inmutable como argumento.

Por esta razón, tiendo a preferir la opción 2. Es decir, el tipo de interfaz presentado es uno donde la cv-ness se puede especificar en cada nivel de indirección. Por supuesto, uno puede eludir la opción 1 escritor de la biblioteca y simplemente usar foo , abriéndose a todo tipo de horror cuando el escritor de la biblioteca cambia la implementación. (Es decir, la opción 1 de escritor de la biblioteca solo percibe que fooRef es parte de la interfaz invariante y que foo puede ir, ir, alterarse, lo que sea. La opción 2 el escritor de la biblioteca percibe que foo es parte de la interfaz invariante).

Estoy más sorprendido de que nadie sugiera construcciones typedef / struct combinadas.
typedef struct { ... } foo;