¿Es una buena idea escribir punteros?
Revisé algo de código y noté que la convención era convertir tipos de puntero como
SomeStruct*
en
typedef SomeStruct* pSomeStruct;
¿Hay algún mérito en esto?
Esto puede ser apropiado cuando el puntero en sí puede considerarse como una "caja negra", es decir, un dato cuya representación interna debe ser irrelevante para el código.
Esencialmente, si su código nunca elimina la referencia al puntero y simplemente lo pasa entre las funciones API (a veces por referencia), entonces el typedef no solo reduce la cantidad de *
mensajes de correo electrónico en su código, sino que también sugiere al programador que el puntero no debería. Realmente no hay que entrometerse.
Esto también facilita cambiar la API en el futuro si surge la necesidad. Por ejemplo, si cambia a usar una ID en lugar de un puntero (o viceversa), el código existente no se romperá porque, en primer lugar, nunca se suponía que se desreferenciara el puntero.
No en mi experiencia. Ocultar el ' *
' hace que el código sea difícil de leer.
La única vez que uso un puntero dentro de typedef es cuando trato con punteros a funciones:
typedef void (*SigCatcher(int, void (*)(int)))(int);
typedef void (*SigCatcher)(int);
SigCatcher old = signal(SIGINT, SIG_IGN);
De lo contrario, los encuentro más confusos que útiles.
La declaración tachada es el tipo correcto de un puntero a la
signal()
función, no del receptor de señal. Podría quedar más claro (usando el SigCatcher
tipo corregido arriba) escribiendo:
typedef SigCatcher (*SignalFunction)(int, SigCatcher);
O, para declarar la signal()
función:
extern SigCatcher signal(int, SigCatcher);
Es decir, a SignalFunction
es un puntero a una función que toma dos argumentos (an int
y a SigCatcher
) y devuelve a SigCatcher
. Y signal()
en sí misma es una función que toma dos argumentos (an int
y a SigCatcher
) y devuelve a SigCatcher
.
Esto puede ayudarle a evitar algunos errores. Por ejemplo en el siguiente código:
int* pointer1, pointer2;
pointer2 no es un int * , es un int simple . Pero con typedefs esto no sucederá:
typedef int* pInt;
pInt pointer1, pointer2;
Ambos son int * ahora.
La discusión se inició asumiendo que el lenguaje de interés es C. No se han considerado las ramificaciones para C++.
Usando un typedef de puntero para una estructura sin etiquetar
La pregunta Tamaño de una estructura que se define como un puntero plantea una interesante perspectiva sobre el uso typedef
de punteros (de estructura).
Considere la definición del tipo de estructura de hormigón sin etiquetas (no opaca):
typedef struct { int field1; double field2; } *Information;
Los detalles de los integrantes son completamente tangenciales a esta discusión; lo único que importa es que este no es un tipo opaco typedef struct tag *tag;
(y no se pueden definir tipos tan opacos typedef
sin una etiqueta).
La pregunta que surge es '¿cómo puedes encontrar el tamaño de esa estructura'?
La respuesta corta es "sólo mediante una variable del tipo". No hay ninguna etiqueta para usar sizeof(struct tag)
. No puede escribir de manera útil , por ejemplo, y sizeof(*Information)
sizeof(Information *)
es el tamaño de un puntero al tipo de puntero, no el tamaño del tipo de estructura.
De hecho, si desea asignar dicha estructura, no puede crear una excepto mediante asignación dinámica (o técnicas sustitutas que imiten la asignación dinámica). No hay manera de crear una variable local del tipo de estructura cuyos punteros se llaman Information
, ni hay una manera de crear una static
variable de alcance de archivo (global o) del tipo de estructura, ni hay una manera de incrustar dicha estructura (como opuesto a un puntero a dicha estructura) en otra estructura o tipo de unión.
Puedes (debes) escribir:
Information info = malloc(sizeof(*info));
Aparte del hecho de que el puntero está oculto en el archivo typedef
, esta es una buena práctica: si el tipo de info
cambio, la asignación de tamaño seguirá siendo precisa. Pero en este caso, también es la única manera de obtener el tamaño de la estructura y asignarla. Y no hay otra forma de crear una instancia de la estructura.
¿Es esto perjudicial?
Depende de tus objetivos.
Este no es un tipo opaco: los detalles de la estructura deben definirse cuando se typedef
'd' el tipo de puntero.
Es un tipo que sólo se puede utilizar con asignación de memoria dinámica.
Es un tipo que no tiene nombre. El puntero al tipo de estructura tiene un nombre, pero el tipo de estructura en sí no.
Si desea imponer la asignación dinámica, esta parece ser una forma de hacerlo.
Sin embargo, en general, es más probable que cause confusión y angustia que esclarecimiento.
Resumen
En general, es una mala idea utilizarlo typedef
para definir un puntero a un tipo de estructura sin etiquetas.