2012-02-15 20 views
8

No soy un experto en lenguajes de programación no orientados a objetos de nivel inferior, y estoy escribiendo un código C para un proyecto en el trabajo. Intento crear algunos tipos de datos abstractos decentes con los que trabajar, y buscar en Google me hizo darme cuenta de que las personas usan ADT basadas en estructuras de dos maneras. Algunas personas definen un tipo de datos como una estructura:¿Cuándo debería tipear def estructura vs. puntero a struct?

typedef struct adt { 
    //content here 
} adt; 

y lo exponen en el mundo en el archivo de encabezado.

Otros definen un tipo de datos como un punteroa struct:

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


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

entiendo que este enfoque le permite typedef struct sin dar al mundo exterior ningún conocimiento de lo que hay dentro de esta estructura, por lo que los programadores puede solo utilizar las funciones suministradas en el mismo archivo de encabezado para operar con este tipo de datos.

¿Hay alguna otra razón para optar por la otra? ¿Existe una "regla empírica" ​​general para cuándo definen los ADT como estructuras y cuándo los definimos como punteros a estructuras?

Respuesta

6

Puede reenviar declarar una estructura sin typedef también - las únicas diferencias son:

  • si la interfaz se ve más limpio, con o sin la palabra clave struct
  • si la interfaz se ve más limpio, con o sin el puntero explícita *

Eg.

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

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

Obviamente esto solo se aplica a las estructuras declaradas hacia adelante en un encabezado de interfaz.

Si no está ocultando la implementación de la estructura en primer lugar, elegir entre S1 y S2 es una cuestión de preferencia (o consistencia). No usaría S3 a menos que sea un tipo realmente opaco/oculto.

La preferencia personal sería usar S1 (palabra clave struct explícita) para agregados grandes/complejos, y S2 para estructuras pequeñas que podría tratar como valores y no siempre pasar por puntero. YMMV.

+0

Para facilitar la lectura tal vez es mejor escribir 'typedef struct S3_s * S3' en lugar de' typedef struct S3_s * S3', ¿no? – Eregrith

+0

@Eregrith: si utilizas la semántica del lenguaje formal, 'typedef struct S3_s * S3' dice que el declarador' * S3' tiene el tipo 'struct S3_s' y la clase de almacenamiento' typedef', por lo que poner el asterisco con el identificador es en realidad idiomático ; sin embargo, poner el asterisco con el tipo está más en sintonía con la cantidad de personas (¿la mayoría?) que piensan acerca de las declaraciones; en lo que a mí respecta, ambas versiones están bien siempre y cuando seas consecuente ... – Christoph

+0

Acabo de seleccionar ese espaciado para mantener la consistencia con el OP, ya que puedo ver los beneficios de cualquier manera. – Useless

1

La decisión de ocultar o no ocultar le corresponde por completo a usted como diseñador de su biblioteca. Si desea reservarse el derecho de cambiar struct a su voluntad en el futuro, no debe exponer a ninguno de sus miembros al "mundo". Si está proporcionando un struct como medio para comunicarse con su biblioteca en primer lugar (por ejemplo, un struct que representa un punto en 3D), entonces no puede ocultar sus miembros del mundo, ya que sería contrario al propósito.

1

leer las Linus Torvalds post Capítulo 5: typedefs

Cuestiones relacionadas