steemit que poner etiquetas ejemplos cursiva como c char stdint

c - que - Razones para usar(o no) stdint



tags h1 ejemplos (4)

Ya sé que stdint está acostumbrado a cuando se necesitan tamaños de variable específicos para la portabilidad entre plataformas, realmente no tengo ese problema por el momento, pero ¿cuáles son los inconvenientes y ventajas de usarlo además del hecho ya presentado arriba?

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

  • 1 - este habla sobre la portabilidad del stdint.

  • 2 - este es más específico sobre 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 es que uint8_t es más limpio que el char sin signo (para almacenar un valor de canal RBG, por ejemplo) , int32_t parece más significativo que simplemente int, etc.

Entonces, mi pregunta es, ¿cuáles son las desventajas, y especialmente las ventajas de usar stdint además de la portabilidad, y debería usarlo solo en algunas partes específicas de mi código, o en todas partes? si en todas partes, ¿cómo puedo usar funciones como atoi, strtok, etc. con él?

¡Gracias!


Pros

El uso de tipos bien definidos hace que el código sea mucho más fácil y seguro para el puerto, ya que no obtendrá 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.

El uso de int También hace que sea difícil detectar promociones de tipo peligroso.

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

Si desea dar pistas al compilador de que una variable debe optimizarse, puede usar uint_fastx_t que le dice al compilador que use el tipo de 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 optimizar el tamaño de los tipos, independientemente de lo que haya escrito. Entre los puntos de secuencia, el compilador puede cambiar implícitamente el tipo a otro diferente de lo especificado, siempre que no afecta el resultado

Contras

Ninguna.

Referencia: MISRA-C: 2004 regla 6.3. "Se utilizarán typedefs que indiquen tamaño y signación en lugar de los tipos básicos".

EDITAR: Se eliminó el ejemplo incorrecto.


contras

La razón principal por la cual 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 habilitaron e invitaron específicamente al implementador del compilador a utilizar los datos de tamaño de datos naturales nativos para la velocidad y la eficiencia del tamaño del código.

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

Insistir en que una arquitectura en particular use un tamaño particular para contar es una mala idea , a pesar de que parece facilitar otras cosas.

En cierto modo, gracias a XML y sus hermanos, el tamaño del tipo de datos nuevamente 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 una excepción más que una regla.


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

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

  • leer / escribir disco / red (pero luego también debe usar las funciones de conversión endian)
  • cuando desee un comportamiento envolvente sin signo en un corte exacto (pero esto se puede hacer de forma más portátil con el operador & ).
  • cuando está controlando el diseño exacto de una estructura porque necesita asegurarse de que no exista relleno (por ejemplo, para memcmp o hashing).

Por otro lado, los tipos uint_least8_t , etc. son útiles en cualquier lugar que desee evitar el uso de tipos uint_least8_t grandes o lentos, pero deben asegurarse de que puede almacenar valores de cierta magnitud. Por ejemplo, mientras long long sea ​​al menos 64 bits, podría 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 un desperdicio en tales máquinas. int_least64_t resuelve el problema.

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

Por último, tenga en cuenta que los argumentos que algunas respuestas han int32_t sobre la ineficacia del uso de int32_t para un contador cuando no es el tamaño entero nativo son técnicamente mayormente correctos, pero es irrelevante para corregir el código. A menos que esté contando un pequeño número de cosas donde la cuenta máxima está bajo su control, o alguna cosa externa (que no esté en la memoria de su programa) donde el recuento puede ser astronómico, el tipo correcto para contar es casi siempre size_t . Esta es la razón por la cual todas las funciones C estándar usan size_t para conteos. No considere usar nada más a menos que tenga una muy buena razón.


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

La razón obvia para no 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 duplicados de código feo si proporcionó una uint*_t versión de, digamos, qsort() para cada expansión de * .

En mi caso, utilizo mis propios tipos, derivados de size_t cuando soy flojo o el número entero sin signo más grande soportado en la plataforma cuando no lo soy.

Editar, porque me encontré con este problema antes:
Creo que es digno de mención que al menos uint8_t , uint32_t y uint64_t están rotos en Solaris 2.5.1. Por lo tanto, para una máxima portabilidad, aún sugiero evitar el uso de stdint.h (al menos durante los próximos años).