我如何确定我的CPU的字长?如果我理解正确,int
应该是一个字长对吧?但我不确定自己是否正确。
所以,只需打印sizeof(int)
就足以确定处理器的字长了吗?
你对于 int 类型所占的字节数的假设是不正确的,请参考这里。
由于在编译时必须知道处理器、操作系统和编译器,因此可以使用编译器提供的预定义的架构/操作系统/编译器宏来推断字长。
然而,在更简单和大多数 RISC 处理器上,字长、总线宽度、寄存器大小和内存组织通常是一致的,但是对于具有不同浮点寄存器、累加器、总线宽度、缓存宽度、通用寄存器等大小的更复杂的 CISC 和 DSP 架构,情况可能并非如此。
当然,这也引出了一个问题,你为什么需要知道这个?通常,你会使用适合应用程序的类型,并相信编译器提供任何优化。如果你认为你需要这些信息进行优化,那么最好使用C99 的 “快速” 类型。如果你需要优化特定算法,则需要针对多种类型实现并进行分析。
int_fast16_t
和int_fast32_t
都是int64_t
,这可能不是一个理想的选择。对于某些情况来说,32位是最快的,并且可以生成更小的代码(更少的REX前缀)。如果您将它们存储在内存中,特别是在数组中,绝对不要使用占用两倍缓存的64位类型。 - Peter Cordes一个int应该是一个单词,对吗?
据我所知,这取决于数据大小模型。关于 UNIX 系统的说明,请参阅64 位和数据大小中立性。例如,Linux 32 位是 ILP32,而 Linux 64 位是 LP64。我不确定在 Windows 系统和版本之间的区别,除了我相信所有 32 位的 Windows 系统都是 ILP32。
如何确定我的 CPU 的字长?
这取决于你采用哪个 C 标准版本和我们谈论的平台是什么。这是一个编译时还是运行时的判断?
C 头文件<limits.h>
可能定义了WORD_BIT
和/或__WORDSIZE
。
__WORDSIZE
在 x86-64 Linux x32 ABI 中是32位(在64位模式下使用寄存器调用ABI的ILP32),所以也不是它。 __SYSCALL_WORDSIZE
在 -mx32
和 -m64
下是64位。但是,在 -m32
下根本没有定义,因此也无法使用,并且可能是Linux或glibc特定的东西。 - Peter Cordessizeof(int)并不总是您的CPU的“字”大小。这里最重要的问题是为什么您想知道字大小……您是在尝试做某种运行时和CPU特定的优化吗?
话虽如此,在Windows上使用Intel处理器,名义上的字大小将是32位或64位,并且您可以轻松找出:
这个答案听起来平凡,但对于第一顺序来说是正确的。但是有一些重要的微妙之处。即使现代Intel或AMD处理器上的x86寄存器宽度为64位;您只能(容易地)在32位程序中使用它们的32位宽度-即使您正在运行64位操作系统。这在Linux和OSX上也是如此。
此外,在大多数现代CPU上,数据总线宽度比标准ALU寄存器(EAX,EBX,ECX等)宽。这个总线宽度可能会有所变化,有些系统具有128位甚至192位的宽总线。
如果您担心性能,则还需要了解L1和L2数据缓存的工作原理。请注意,一些现代CPU具有L3缓存。缓存包括一个称为写缓冲区的单元。
char到long long)。
测量每个版本在运行算法时花费的时间。如果有一个特定版本的运行时间明显比其他版本更短,则用于该版本的字长大小可能是计算机的本机字长大小。另一方面,如果有几个版本的运行时间相差不大,请选择具有更大字长的版本。
请注意,即使使用此技术也可能会得到虚假数据:使用Turbo C编译并在DOS上通过80386处理器运行的基准测试将报告字长为16位,仅因为编译器不使用32位寄存器执行整数算术,而是调用内部函数来执行每个算术运算的32位版本。
a += b; b += a;
(斐波那契数列)这样做几百万次(使用 unsigned
类型,因为它 将 溢出)。它不太可能被优化掉,并且不依赖于内存。 - Peter Cordesuint16_t
vs. uint32_t
vs. uint64_t
vs. __uint128_t
的决策。 - Peter Cordes#include <stdio.h>
int main ()
{
long l;
short s = (8 * sizeof(l));
printf("Word size of this machine is %hi bits\n", s);
return 0;
}
stdint.h
中有一些有用的数据类型,或者编译器特定或平台特定的宏用于各种目的。sizeof(void*)
无论出于何种原因了解处理器的大小,都不重要。
处理器的大小是指单个CPU核心算术逻辑单元(ALU)可以在单个时间点上处理的数据量。 CPU核心的ALU将始终在累加器寄存器上工作。因此,CPU的位数大小是累加器寄存器的位数大小。
您可以从处理器的数据表中或通过编写小型汇编语言程序来查找累加器的大小。
请注意,某些处理器(如ARM)中累加器寄存器的有效可用大小可能会根据操作模式(Thumb和ARM模式)而变化。这意味着处理器的大小也会根据该处理器的模式而变化。
在许多体系结构中,虚拟地址指针大小和整数大小与累加器大小相同。这仅是为了利用不同处理器操作中的累加器寄存器,但这不是硬性规定。
正如其他人所指出的,你对计算这个值感兴趣的方式是怎样的?有很多变量需要考虑。
sizeof(int) != sizeof(word)。byte、word、double word 的大小自它们被创建以来至少在 Windows API 世界中为了 API 兼容性而从未改变。即使处理器的字长大小是指令可以操作的自然大小。例如,在 msvc/cpp/c# 中,sizeof(int) 是四个字节。即使在 64 位编译模式下也是如此。Msvc/cpp 有 __int64,而 c# 有 Int64/UInt64(非 CLS 兼容)的 ValueType。在 win32 API 中还有 WORD DWORD 和 QWORD 的类型定义,分别从未改变过两个字节、四个字节和八个字节。在 Win32 上还有 UINT/INT_PTR 和在 c# 上有 UIntPtr/IntPtr,它们保证足够大来表示一个内存地址和一个引用类型。据我所知,如果架构仍然存在,我可能会错,我认为没有人需要处理,也不存在 near/far 指针,因此,如果你使用 c/cpp/c#,sizeof(void*) 和 Unsafe.SizeOf{IntPtr}() 将足以以符合标准的跨平台方式确定您的最大“字”大小。如果有人能纠正这一点,请这样做!此外,在 c/cpp 中,内在类型的大小定义不明确。
sizeof
返回字符数,标准仅指定每个字符至少为8位。 - Pascal Cuoq