Los compiladores de AFAIK solo definen sus propias versiones de los tipos (u)int_(fast/least)XX_t
si aún no están definidos por el sistema. Eso es porque es muy importante que estos tipos estén igualmente definidos en todas las bibliotecas/binarios en un solo sistema.De lo contrario, si los diferentes compiladores definirían esos tipos de manera diferente, una biblioteca construida con CompilerA puede tener un tipo diferente de uint_fast32_t
que un binario construido con CompilerB, pero este binario aún puede enlazarse con la biblioteca; no hay requisito estándar formal que todo el código ejecutable de un sistema tenga que ser construido por el mismo compilador (en realidad en algunos sistemas, por ejemplo, Windows, es bastante común que el código haya sido compilado por todo tipo de compiladores diferentes). Si ahora este binario llama a una función de la biblioteca, ¡las cosas se romperán!
Entonces, la pregunta es: ¿realmente GCC está definiendo uint_fast16_t aquí, o es realmente Linux (me refiero al núcleo aquí) o quizás incluso el estándar C Lib (glibc en la mayoría de los casos) que define esos tipos? Ya que si Linux o glibc los define, los GCC basados en ese sistema no tienen más opción que adoptar las convenciones que estos establezcan. Lo mismo es cierto para todos los demás tipos de ancho variable: char
, short
, int
, long
, long long
; todos estos tipos tienen solo un ancho de bits mínimo garantizado en C Standard (y para int
en realidad es de 16 bits, por lo que en plataformas donde int
es de 32 bits, ya es mucho más grande de lo que requeriría la norma).
Aparte de eso, en realidad me pregunto qué está mal con su CPU/compilador/sistema. En mi sistema, la multiplicación de 64 bits es igual de rápida que la multiplicación de 32 bits. He modificado el código para poner a prueba 16, 32 y 64 bits:
#include <time.h>
#include <stdio.h>
#include <inttypes.h>
#define RUNS 100000
#define TEST(type) \
static type test ## type() \
{ \
int count; \
type p, x; \
\
p = 1; \
for (count = RUNS; count != 0; count--) { \
for (x = 1; x != 50000; x++) { \
p *= x; \
} \
} \
return p; \
}
TEST(uint16_t)
TEST(uint32_t)
TEST(uint64_t)
#define CLOCK_TO_SEC(clock) ((double)clockTime/CLOCKS_PER_SEC)
#define RUN_TEST(type) \
{ \
clock_t clockTime; \
unsigned long long result; \
\
clockTime = clock(); \
result = test ## type(); \
clockTime = clock() - clockTime; \
printf("Test %s took %2.4f s. (%llu)\n", \
#type, CLOCK_TO_SEC(clockTime), result \
); \
}
int main()
{
RUN_TEST(uint16_t)
RUN_TEST(uint32_t)
RUN_TEST(uint64_t)
return 0;
}
El uso de código no optimizado (-O0), me sale:
Test uint16_t took 13.6286 s. (0)
Test uint32_t took 12.5881 s. (0)
Test uint64_t took 12.6006 s. (0)
El uso de código optimizado (O3), me sale:
Test uint16_t took 13.6385 s. (0)
Test uint32_t took 4.5455 s. (0)
Test uint64_t took 4.5382 s. (0)
La segunda salida es bastante interesante. @R .. escribió en un comentario anterior:
En x86_64, 32 bits aritmética nunca debe ser más lenta de 64 bits aritmética, y punto.
El segundo resultado muestra que no se puede decir lo mismo para la aritmética de 32/16 bit. La aritmética de 16 bits puede ser significativamente más lenta en una CPU de 32/64 bits, aunque mi CPU x86 puede realizar de forma nativa una aritmética de 16 bits; a diferencia de algunas otras CPU, como un PPC, por ejemplo, que solo puede realizar aritmética de 32 bits. Sin embargo, esto solo parece aplicarse a la multiplicación en mi CPU, al cambiar el código para hacer la suma/resta/división, ya no hay diferencia significativa entre 16 y 32 bits.
Los resultados anteriores provienen de un Intel Core i7 (2,66 GHz), pero si alguien está interesado, puedo ejecutar este benchmark también en un Intel Core 2 Duo (una generación más anterior) y en un Motorola PowerPC G4.
Solo un pequeño consejo: no es necesario que incluya ambos, * stdint.h * y * inttypes.h *; de acuerdo con el estándar ISO C, * inttypes.h * siempre debe incluir * stdint.h *, por lo que incluirlo primero es solo una pérdida de tiempo (no es que esté prohibido o sea incorrecto, simplemente innecesario). – Mecki