(u)int_(fast/least)XX_t
如果系统尚未定义这些类型,AFAIK 编译器只会定义它们自己的类型版本。这是因为在单个系统上的所有库/二进制文件中同样定义这些类型非常重要。否则,如果不同的编译器对这些类型的定义不同,则使用 CompilerA 构建的库可能与使用 CompilerBuint_fast32_t
构建的二进制文件具有不同的类型,但该二进制文件仍可能链接到该库;没有正式的标准要求系统的所有可执行代码必须由相同的编译器构建(实际上在某些系统上,例如 Windows,代码由各种不同的编译器编译是相当普遍的)。如果现在这个二进制文件调用库的函数,事情就会崩溃!
所以问题是:真的是 GCC 在这里定义了 uint_fast16_t,还是实际上是 Linux(我指的是这里的内核)或者甚至是定义这些类型的标准 C Lib(在大多数情况下是 glibc)?因为如果 Linux 或 glibc 定义了这些,构建在该系统上的 GCC 除了采用这些已经建立的任何约定外别无选择。所有其他可变宽度类型也是如此:char
, short
, int
, long
, long long
; 所有这些类型在C 标准中只有一个最小保证位宽(因为int
它实际上是 16 位,所以在int
32 位的平台上,它已经比标准要求的要大得多)。
除此之外,我实际上想知道您的 CPU/编译器/系统出了什么问题。在我的系统上,64 位乘法与 32 位乘法一样快。我修改了您的代码以测试 16、32 和 64 位:
#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;
}
使用未优化的代码(-O0),我得到:
Test uint16_t took 13.6286 s. (0)
Test uint32_t took 12.5881 s. (0)
Test uint64_t took 12.6006 s. (0)
使用优化代码(-O3),我得到:
Test uint16_t took 13.6385 s. (0)
Test uint32_t took 4.5455 s. (0)
Test uint64_t took 4.5382 s. (0)
第二个输出非常有趣。@R.. 在上面的评论中写道:
在 x86_64 上,32 位算术永远不应该比 64 位算术慢。
第二个输出表明对于 32/16 位算术不能说同样的事情。16 位算术在 32/64 位 CPU 上可能会明显变慢,即使我的 x86 CPU 本身可以执行 16 位算术;与其他一些 CPU 不同,例如 PPC,它只能执行 32 位运算。但是,这似乎只适用于我的 CPU 上的乘法,当更改代码以进行加法/减法/除法时,16 位和 32 位之间不再存在显着差异。
上面的结果来自 Intel Core i7 (2.66 GHz),但如果有人感兴趣,我也可以在 Intel Core 2 Duo(上一代 CPU)和 Motorola PowerPC G4 上运行这个基准测试。