En C, ¿es una buena forma usar typedef para un puntero?

4 minutos de lectura

Considere el siguiente código C:

typedef char * MYCHAR;
MYCHAR x;

Tengo entendido que el resultado sería que x es un puntero de tipo “char”. Sin embargo, si la declaración de x ocurriera lejos del comando typedef, un lector humano del código no sabría inmediatamente que x es un puntero. Alternativamente, uno podría usar

typedef char MYCHAR;
MYCHAR *x;

¿Cuál se considera mejor forma? ¿Es esto más que una cuestión de estilo?

  • Es cuestión de gustos (y reglas de codificación). Personalmente, no me gusta esconder “puntualidad” en typedefentonces no me gusta typedef char* MYSTRING; en absoluto…

    – Basile Starynkevitch

    16 de junio de 2013 a las 15:52


Si el puntero nunca está destinado a ser desreferenciado o manipulado directamente (IOW, solo lo pasa como un argumento a una API), entonces está bien ocultar el puntero detrás de un typedef.

De lo contrario, es mejor hacer explícita la “puntualidad” del tipo.

  • Los punteros a tipos incompletos son perfectamente válidos como argumentos de función, y tampoco puede desreferenciarlos. OIA: Tú no necesidad para esconderlos detrás de definiciones de tipo tontas, ni siquiera en una API “secreta”.

    – salvaje

    16 de junio de 2013 a las 16:16

  • @wildplasser: creo que el punto no es que sea una buena práctica ocultar un puntero en tipos opacos (que simplemente pasa), sino que es una mala práctica ocultar punteros cuando deben tratarse como tales (por ejemplo, el horrible typedef char * string;).

    – Mateo Italia

    16 de junio de 2013 a las 16:38

  • Respuesta simple y concisa. También podría agregar el hecho de que al crear tipos de puntero, uno podría necesitar crear const-versiones calificadas de ellos, por razones que seguramente conoces.

    – alecov

    17 de junio de 2013 a las 3:52

avatar de usuario
Hormiga

Usaría definiciones de tipo de puntero solo en situaciones en las que la naturaleza del puntero del tipo resultante no tiene importancia. Por ejemplo, pointer typedef se justifica cuando uno quiere declarar un tipo de “manejador” opaco que simplemente se implementa como un puntero, pero se supone que el usuario no puede utilizarlo como un puntero.

typedef struct HashTableImpl *HashTable;
/* 'struct HashTableImpl' is (or is supposed to be) an opaque type */

En el ejemplo anterior, HashTable es un “mango” para una tabla hash. El usuario recibirá ese identificador inicialmente de, digamos, CreateHashTable función y pásela a, digamos, HashInsert función y tal. Se supone que al usuario no le importa (ni siquiera sabe) que HashTable es un puntero.

Pero en los casos en que se supone que el usuario debe comprender que el tipo es en realidad un puntero y se puede usar como puntero, las definiciones de tipo de puntero ofuscan significativamente el código. Los evitaría. Declarar punteros explícitamente hace que el código sea más legible.

Es interesante notar que la biblioteca estándar de C evita tales definiciones de tipo de puntero. Por ejemplo, FILE obviamente está destinado a ser utilizado como un tipo opaco, lo que significa que la biblioteca podría haberlo definido como typedef FILE <some pointer type> en lugar de hacernos usar FILE * todo el tiempo. Pero por alguna razón decidieron no hacerlo.

No me gusta particularmente typedef para un puntero, pero tiene una ventaja. Elimina la confusión y los errores comunes cuando declara más de una variable de puntero en una sola declaración.

typedef char *PSTR;
...
PSTR str1, str2, str3;

es posiblemente más claro que:

char *str1, str2, str3;  // oops

  • Es una buena consecuencia, pero esa consecuencia es una mala razón en sí misma para typedef 🙂

    – klutt

    19 de noviembre de 2021 a las 10:03

prefiero dejar el *, muestra que hay un puntero. Y su segundo ejemplo debe acortarse como char* x;no tiene sentido.

También creo que esto es una cuestión de estilo/convención. En la biblioteca Core Graphics de Apple, con frecuencia “ocultan” el puntero y usan la convención de agregar “Ref” al final del tipo. Así por ejemplo, CGImage * corresponde a CGImageRef. De esa manera, aún sabrá que es una referencia de puntero.

avatar de usuario
Ziffusión

Otra forma de verlo es desde la perspectiva de tipos. Un tipo define las operaciones que son posibles en ese tipo y la sintaxis para invocar estas operaciones. Desde esta perspectiva, MYCHAR es lo que sea. Es responsabilidad de los programadores conocer las operaciones permitidas en él. Si se declara como el primer ejemplo, entonces admite el operador *. Siempre puede nombrar el identificador apropiadamente para aclarar su uso.

Otros casos en los que es útil declarar un tipo que es un puntero es cuando la naturaleza del parámetro es opaca para el usuario (programador). Puede haber API que deseen devolver un puntero al usuario y esperar que el usuario se lo devuelva a la API en algún otro momento. Como un identificador opaco o una cookie, para ser utilizado por la API solo internamente. Al usuario no le importa la naturaleza del parámetro. Tendría sentido no enturbiar las aguas ni exponer su naturaleza exacta al exponer el * en la API.

avatar de usuario
glglgl

Si observa varias API existentes, parece que no poner el puntero en el tipo parece un mejor estilo:

y probablemente muchos otros.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad