¿Qué es uint_fast32_t y por qué debería usarse en lugar del int y uint32_t regulares?

110

Entonces, el motivo de typedef: ed tipos de datos primitivos es abstraer la representación de bajo nivel y hacer que sea más fácil de comprender (en uint64_tlugar del long longtipo, que es de 8 bytes).

Sin embargo, hay uint_fast32_tque tiene el mismo typedefque uint32_t. ¿El uso de la versión "rápida" hará que el programa sea más rápido?

Amumu
fuente
long long quizás no sea de 8 bytes, es posible tener long long con 1 byte (en caso de que CHAR_BIT sea al menos 64) o con 3738383 bytes. también uint64_t puede tener 1, 2, 4 u 8 bytes, CHAR_BIT debe ser 64, 3, 16 u 8 para eso.
12431234123412341234123

Respuestas:

134
  • intpuede ser tan pequeño como 16 bits en algunas plataformas. Puede que no sea suficiente para su aplicación.
  • uint32_tno se garantiza que exista. Es un opcional typedefque la implementación debe proporcionar si tiene un tipo entero sin signo de exactamente 32 bits. Algunos tienen bytes de 9 bits, por ejemplo, por lo que no tienen un uint32_t.
  • uint_fast32_testablece su intención claramente: es un tipo de al menos 32 bits que es el mejor desde el punto de vista del rendimiento. uint_fast32_tpuede tener de hecho 64 bits de longitud. Depende de la implementación.

... hay uint_fast32_tque tiene el mismo typedef que uint32_t...

Lo que está viendo no es el estándar. Es una implementación particular (BlackBerry). Entonces no se puede deducir de ahí que uint_fast32_tsea ​​siempre lo mismo que uint32_t.

Ver también:

Yakov Galka
fuente
35
Buena respuesta. Para completar, tal vez se podría señalar la diferencia uint_least32_ttambién, que es lo mismo, uint_fast32_texcepto que favorece una tienda más pequeña en lugar de la velocidad.
Damon
2
¿Por qué el número entero más rápido que tiene al menos 32 bits de ancho sería mayor que 32 bits? Siempre pensé que si hay menos bits, habrá menos bits en los que la CPU tendrá que trabajar, por lo tanto, más rápido. ¿Que me estoy perdiendo aqui?
Shane Hsu
12
@ShaneHsu: digamos que una CPU de 64 bits tendrá un verano de 64 bits, que suma números de 64 bits en un ciclo. No importa si todo lo que quiere hacer es trabajar con números de 32 bits, no será más rápido que un ciclo. Ahora, aunque no es así en x86 / amd64, es posible que los enteros de 32 bits ni siquiera sean direccionables. En tal caso, trabajar en ellos requiere operaciones adicionales para extraer los 32 bits de, digamos, unidades alineadas de 64 bits. Consulte también la pregunta vinculada. El estándar C ++ está escrito para que pueda funcionar en una máquina que tenga palabras de 37 bits ... así que no hay ningún tipo de 32 bits.
Yakov Galka
42

La diferencia radica en su exactitud y disponibilidad.

El doc aquí dice:

tipo entero sin signo con un ancho de exactamente 8, 16, 32 y 64 bits respectivamente ( proporcionado solo si la implementación admite directamente el tipo ):

uint8_t
uint16_t
uint32_t
uint64_t

Y

el tipo entero sin signo sin signo más rápido con un ancho de al menos 8, 16, 32 y 64 bits respectivamente

uint_fast8_t
uint_fast16_t
uint_fast32_t
uint_fast64_t    

Entonces, la diferencia es bastante clara: uint32_tes un tipo que tiene exactamente 32 bits, y una implementación debe proporcionarlo solo si tiene un tipo con exactamente 32 bits, y luego puede typedef ese tipo como uint32_t. Esto significa uint32_tque puede estar disponible o no .

Por otro lado, uint_fast32_tes un tipo que tiene al menos 32 bits, lo que también significa que si una implementación puede typedef uint32_tcomo uint_fast32_t si lo proporciona uint32_t. Si no lo proporciona uint32_t, entonces uint_fast32_tpodría ser un typedef de cualquier tipo que tenga al menos 32bits.

Nawaz
fuente
3
Pero, ¿cuál es la razón que hace que, por ejemplo, uint_fast32_t sea más rápido que uint32_t? ¿Por qué es más rápido?
Destructor
2
@PravasiMeet: No se accede a todos los enteros de la misma manera. Algunos son más fáciles de acceder que otros. Más fácil significa menos computación, más directo, lo que resulta en un acceso más rápido. Ahora uint32_tes exactamente de 32 bits en todos los sistemas (si existe), lo que podría no ser más rápido en comparación con el que tiene, digamos, 64 bits. uint_fast32_tpor otro lado, al menos de 32 bits, podría ser incluso de 64 bits.
Nawaz
10
@Destructor: en algunos procesadores, si una variable se almacena en un registro que es más largo, es posible que el compilador tenga que agregar código adicional para eliminar los bits adicionales. Por ejemplo, si uint16_t x;se almacena en un registro de 32 bits en el ARM7-TDMI, es posible que el código x++;deba evaluarse como x=((x+1)<<16)>>16);. En los compiladores para esa plataforma, uint_fast16_tlo más probable es que se defina como sinónimo uint32_tde evitar eso.
supercat
¿Por qué [u]int_(fast|least)N_tno son también opcionales? Seguramente no todas las arquitecturas son requeridas por el Estándar para soportar tipos primitivos de al menos 64 bits. Sin embargo, la redacción de stdint.himplica que deben hacerlo. Me parece extraño que hayamos estado imponiendo eso desde 1999, algunos años antes de que la informática de 64 bits se convirtiera en la corriente principal, por no hablar del retraso (en muchos casos todavía actual) de las arquitecturas integradas. Esto me parece un gran descuido.
underscore_d
1
@underscore_d: No hay ninguna razón en particular, por ejemplo, por la que el Estándar no pueda ser aplicable a una implementación de PIC12 con 16 bytes de RAM de datos y espacio para 256 instrucciones. Tal implementación necesitaría rechazar muchos programas, pero eso no debería impedir que se comporte de manera definida para programas cuyas necesidades podría satisfacer.
supercat
4

Cuando estás #include inttypes.hen tu programa, tienes acceso a un montón de formas diferentes de representar números enteros.

El tipo uint_fast * _t simplemente define el tipo más rápido para representar un número determinado de bits.

Piénsalo de esta manera: defines una variable de tipo shorty la usas varias veces en el programa, lo cual es totalmente válido. Sin embargo, el sistema en el que está trabajando podría funcionar más rápidamente con valores de tipo int. Al definir una variable como tipo uint_fast*t, la computadora simplemente elige la representación más eficiente con la que puede trabajar.

Si no hay diferencia entre estas representaciones, entonces el sistema elige la que desea y la usa de manera consistente en todo momento.

Harley Sugarman
fuente
9
¿Por qué inttypes.hy no stdint.h? Parece que inttypes.h solo contiene varias pelusas ligeramente útiles, además de una inclusión de stdint.h?
Lundin
@underscore_d Sé la diferencia. Pero, ¿quién usa stdio.h en programas profesionales, sin importar el área de aplicación?
Lundin
@Lundin ¡No tengo ni idea de quiénes son ni de si existen! Pensé que podría ser útil proporcionar un enlace que explique qué es esa "pelusa ligeramente útil" ;-) Quizás ayude a las personas a darse cuenta de que tienes razón y que no la necesitan.
underscore_d
-1

Tenga en cuenta que la versión rápida podría tener más de 32 bits. Si bien el int rápido encajará bien en un registro y estará alineado y similares: pero, usará más memoria. Si tiene matrices grandes de estos, su programa será más lento debido a más aciertos de memoria caché y ancho de banda.

No creo que el CPUS moderno se beneficie de fast_int32, ya que generalmente el signo que se extiende de 32 a 64 bits puede ocurrir durante la instrucción de carga y la idea de que existe un formato de entero 'nativo' que es más rápido es anticuada.

Gil Colgate
fuente