¿Es una buena idea escribir punteros?

Resuelto Unknown asked hace 15 años • 15 respuestas

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?

Unknown avatar Apr 15 '09 10:04 Unknown
Aceptado

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.

Artelius avatar Apr 15 '2009 03:04 Artelius

No en mi experiencia. Ocultar el ' *' hace que el código sea difícil de leer.

sigjuice avatar Apr 15 '2009 03:04 sigjuice

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 SigCatchertipo corregido arriba) escribiendo:

 typedef SigCatcher (*SignalFunction)(int, SigCatcher);

O, para declarar la signal()función:

 extern SigCatcher signal(int, SigCatcher);

Es decir, a SignalFunctiones un puntero a una función que toma dos argumentos (an inty a SigCatcher) y devuelve a SigCatcher. Y signal()en sí misma es una función que toma dos argumentos (an inty a SigCatcher) y devuelve a SigCatcher.

Jonathan Leffler avatar Apr 15 '2009 03:04 Jonathan Leffler

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.

Sad Developer avatar Apr 15 '2009 03:04 Sad Developer

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 typedefde 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 typedefsin 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 sizeof(*Information), por ejemplo, y 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 staticvariable 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 infocambio, 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 typedefpara definir un puntero a un tipo de estructura sin etiquetas.

Jonathan Leffler avatar Apr 09 '2017 19:04 Jonathan Leffler