Razones para usar (o no) stdint


Ya sé que stdint está acostumbrado cuando necesita tamaños variables específicos para la portabilidad entre plataformas, realmente no tengo ese problema por ahora, pero ¿cuáles son los contras y pros de usarlo además del hecho ya mostrado anteriormente?

Buscándolo en stackoverflow y otros sitios, encontré 2 enlaces que tratan sobre el tema:

  • 1 - este habla de la portabilidad del stdint.

  • 2 - este es más específico acerca de uint8_t.

Estos dos enlaces son geniales especialmente para saber más sobre la razón principal de este encabezado que es la portabilidad, pero para mí, lo que más me gusta de él es que creo que uint8_t es más limpio que unsigned char (para almacenar un valor de canal RBG, por ejemplo), int32_t parece más significativo que simplemente int, etc.

Entonces, mi pregunta es, exactamente cuáles son los contras, y especialmente los pros de usar stdint además de la portabilidad, y debería usarlo solo en algunos partes específicas de mi código, o en todas partes? si en todas partes, ¿cómo puedo usar funciones como atoi, strtok, etc.?

Gracias!

Author: Community, 2012-03-23

4 answers

Pros

El uso de tipos bien definidos hace que el código sea mucho más fácil y seguro de portar, ya que no tendrá sorpresas cuando, por ejemplo, una máquina interpreta int como 16 bits y otra como 32 bits. Con stdint.h, lo que escribes es lo que obtienes.

Usando int etc también hace que sea difícil detectar promociones de tipo peligroso.

Otra ventaja es que al usar int8_t en lugar de char, sabes que siempre obtienes una variable de 8 bits con signo. char puede ser firmado o sin firmar, es comportamiento definido por la implementación y varía entre compiladores. Por lo tanto, el valor predeterminado char es muy peligroso de usar en código que debería ser portable.

Si desea dar pistas al compilador de que una variable debe ser optimizada, puede usar el uint_fastx_t que le dice al compilador que use el tipo entero más rápido posible, al menos tan grande como 'x'. La mayoría de las veces esto no importa, el compilador es lo suficientemente inteligente como para hacer optimizaciones en los tamaños de tipo sin importar lo que haya escrito. Entre los puntos de secuencia, el compilador puede cambiar implícitamente el tipo a otro que el especificado, siempre y cuando no afecte el resultado.

Cons

Ninguna.


Referencia: MISRA-C:2004 regla 6.3." typedefs that indicate size and signedness shall be used in place of the basic types".

EDITAR: Ejemplo incorrecto eliminado.

 61
Author: Lundin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-21 14:09:28

La única razón para usar uint8_t en lugar de unsigned char (aparte de la preferencia estética) es si desea documentar que su programa requiere char para ser exactamente 8 bits. uint8_t existe si y solo si CHAR_BIT==8, según los requisitos de la norma C.

El resto de los tipos intX_t y uintX_t son útiles en las siguientes situaciones:

  • lectura / escritura de disco / red (pero luego también tiene que usar funciones de conversión endian)
  • cuando se quiere unsigned wraparound comportamiento en un corte exacto(pero esto se puede hacer más portablemente con el operador &).
  • cuando está controlando el diseño exacto de una estructura porque necesita asegurarse de que no existe relleno (por ejemplo, para memcmp o con fines de hash).

Por otro lado, el uint_least8_t, etc. los tipos son útiles en cualquier lugar en el que desee evitar el uso de tipos desperdiciadamente grandes o lentos, pero debe asegurarse de que puede almacenar valores de cierta magnitud. Por ejemplo, mientras long long tiene al menos 64 bits, puede ser de 128 bits en algunas máquinas, y usarlo cuando lo que necesita es solo un tipo que puede almacenar números de 64 bits sería muy derrochador en tales máquinas. int_least64_t resuelve el problema.

Evitaría usar los tipos [u]int_fastX_t completamente ya que a veces han cambiado en una máquina dada (rompiendo el ABI) y ya que las definiciones generalmente son incorrectas. Por ejemplo, en x86_64, el tipo entero de 64 bits se considera el "rápido" para valores de 16, 32 y 64 bits, pero mientras que la adición, la resta y la multiplicación son exactamente la misma velocidad ya sea que use valores de 32 bits o 64 bits, la división es casi seguramente más lenta con tipos más grandes de lo necesario, e incluso si fueran la misma velocidad, está usando el doble de la memoria sin ningún beneficio.

Finalmente, tenga en cuenta que los argumentos que algunas respuestas han hecho sobre la ineficiencia de usar int32_t para un contador cuando no es el tamaño entero nativo son técnicamente correctos, pero es irrelevante corregir el código. A menos que estés contando un pequeño número de cosas donde el conteo máximo está bajo su control, o alguna cosa externa (no en la memoria de su programa) donde el conteo podría ser astronómico, el tipo correcto para un conteo es casi siempre size_t. Esta es la razón por la que todas las funciones C estándar utilizan size_t para los recuentos. No considere usar nada más a menos que tenga una muy buena razón.

 16
Author: R..,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-23 12:13:22

Cons

La razón principal por la que el lenguaje C no especifica el tamaño de int o long, etc. es para la eficiencia computacional. Cada arquitectura tiene un tamaño natural y más eficiente, y los diseñadores específicamente facultaron e intentaron que el implementador del compilador usara los datos de tamaño de datos nativos naturales para la velocidad y la eficiencia del tamaño del código.

En años pasados, la comunicación con otras máquinas no era una preocupación principal-la mayoría de los programas eran locales a la máquina - por lo que la previsibilidad el tamaño de cada tipo de datos era de poca preocupación.

Insistir en que una arquitectura en particular use un tamaño particular int para contar es realmente una mala idea, a pesar de que parecería hacer otras cosas más fáciles.

En cierto modo, gracias a XML y sus hermanos, el tamaño del tipo de datos ya no es una gran preocupación. El envío de estructuras binarias específicas de la máquina de una máquina a otra es de nuevo la excepción en lugar de la regla.

 7
Author: wallyk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-23 06:24:31

Utilizo tipos stdint solo por una razón, cuando los datos que tengo en memoria irán en disco/red/descriptor en forma binaria. Solo tienes que luchar contra el problema de little-endian / big-endian, pero eso es relativamente fácil de superar.

La razón obvia no para usar stdint es cuando el código es independiente del tamaño, en términos matemáticos todo lo que funciona sobre los enteros racionales. Produciría desagradables duplicados de código si proporcionara una versión uint*_t de, por ejemplo, qsort() para cada expansión de *.

Utilizo mis propios tipos en ese caso, derivados de size_t cuando soy perezoso o el mayor número entero sin signo soportado en la plataforma cuando no lo soy.

Editar, porque me encontré con este problema anterior:
Creo que es digno de mención que al menos uint8_t, uint32_t y uint64_t se rompen en Solaris 2.5.1. Así que para la máxima portabilidad todavía sugiero evitar stdint.h (al menos durante los próximos años).

 6
Author: hroptatyr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-05 09:10:10