【问题标题】:How to find out word length of a virtual machine?如何找出虚拟机的字长?
【发布时间】:2020-11-28 00:49:55
【问题描述】:

我安装了 ubuntu/trusty64 vagrant box (https://app.vagrantup.com/ubuntu/boxes/trusty64),我有以下代码:

#include <stdio.h>
int main () {    
  short count = -1;
  int a = 5 ;
  int* a_ptr = &a;  
  char b = 'A';
  char* b_ptr = &b;
  
  printf ("count's value     = %d \n", count);  
  printf ("count's address     = %p \n", &count);  
  printf ("a's value     = %d \n", a);   
  printf ("a's address   = %p \n", &a);    
  printf ("a_ptr value   = %p \n", a_ptr);  
  printf ("a_ptr address = %p \n", &a_ptr);  
  printf ("a_ptr deref'ed= %d \n", *a_ptr);   
  printf ("\n");
  printf ("b's value     = %d \n", b);     
  printf ("b's address   = %p \n", &b);   
  printf ("b_ptr value   = %p \n", b_ptr);  
  printf ("b_ptr address = %p \n", &b_ptr);  
  printf ("b_ptr deref'ed= %d \n", *b_ptr);   
  printf ("\n");      
  
  for (count = -30; count < 500; count++) {
    printf ("test: %3d: %p: (%d, %x)\n", count, b_ptr+count, *(b_ptr+count),*(b_ptr+count)) ;  
  }
}

显示输出:

count's value     = -1
count's address     = 0x7ffd9440876a
a's value     = 5
a's address   = 0x7ffd94408764
a_ptr value   = 0x7ffd94408764
a_ptr address = 0x7ffd94408758
a_ptr deref'ed= 5

b's value     = 65
b's address   = 0x7ffd94408757
b_ptr value   = 0x7ffd94408757
b_ptr address = 0x7ffd94408748
b_ptr deref'ed= 65

test: -15: 0x7ffd94408748: (87, 57)
test: -14: 0x7ffd94408749: (-121, ffffff87)
test: -13: 0x7ffd9440874a: (64, 40)
test: -12: 0x7ffd9440874b: (-108, ffffff94)
test: -11: 0x7ffd9440874c: (-3, fffffffd)
test: -10: 0x7ffd9440874d: (127, 7f)

我只显示0x7ffd94408748处的内容,也就是0x7ffd94408757,也就是b的地址。

请注意,内存地址分布在假定的 64 位处理器上的 6 个内存位置。我测试了其他数据类型,似乎其他数据类型也以每个内存位置最多 8 位表示,因此我得出结论,它是一台 8 位机器。

但是,当我运行 $getconf WORD_BIT 时,我得到 32,当我运行 $uname -a 时,我看到“Linux vagrant-ubuntu-trusty-64 3.13.0-170-generic #220-Ubuntu SMP Thu May 9 12:40:49 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux。”

在我的 VirtualBox 管理器中,我看到这台机器是 64 位 Ubuntu。

这台机器的正确字长是多少?虚拟化是否有一些东西使它的真实字长看起来与所说的不同(即 64 位)?

我在以下位置看到类似的帖子: Determine word size of my processor How to determine whether a given Linux is 32 bit or 64 bit? how to find if the machine is 32bit or 64bit

但是尝试上面的链接显示了 32 和 64 位之间的各种结果,所以我更加困惑。

【问题讨论】:

  • 为什么这么复杂?假设您在不强制 32/64b 的情况下进行编译:sizeof(int) ==sizeof(long) == 4 => 32 位,sizeof(long) == 8 => 64b。你也可以看看sizeof一个指针,或者看看limits.h的定义

标签: c linux operating-system word-size


【解决方案1】:

这台机器的正确字长是多少?

要查找int 或指针等对象的位大小,请使用sizeof

 printf("%zu\n", sizeof(char) * CHAR_BIT);
 printf("%zu\n", sizeof(int) * CHAR_BIT);
 printf("%zu\n", sizeof(long) * CHAR_BIT);
 printf("%zu\n", sizeof(long long) * CHAR_BIT);
 printf("%zu\n", sizeof(void *) * CHAR_BIT);

【讨论】:

    【解决方案2】:

    请注意,内存地址分布在假定的 64 位处理器上的 6 个内存位置。

    不,他们不是。请注意,它们是十六进制地址。

    我断定它是一台 8 位机器。

    在大多数架构(但不是全部)中,每个地址覆盖的确实是 8 位。请检查CHAR_BIT 以确保改为。

    这台机器的正确字长是多少?

    这取决于您对“字长”的定义。有些人认为这是给定架构可用的最大整数寄存器大小。其他人谈论指针大小。其他关于 C 中 int 的大小 供应商实施。

    在 C 中没有简单的方法来检查它,因为每个环境都可以定义具有他们喜欢的限制的标准类型。相反,如果您需要精确的大小,您应该使用&lt;stdint.h&gt; 中的整数类型。

    【讨论】:

    • "word length" 我的意思是一个数据位置的宽度。所以用你的话来说:“每个地址涵盖了多少。”
    • 我从来没有听说过这样的“字长”定义,但如果你愿意的话,它是CHAR_BIT,而且几乎普遍是每字节 8 位。不过,有些架构在对齐等方面有限制。
    【解决方案3】:

    所有当前的 Linux 架构都是 ILP32 或 LP64。

    ILP32 具有 32 位 intlong int 和指针类型。 (通常,此类硬件中的通用寄存器是 32 位的。)

    LP64 有 32 位 int,但有 64 位 long int 和指针类型。 (通常,此类硬件中的通用寄存器是 64 位的。)

    (与 Windows 相比,在 32 位 x86 上是 ILP32,但在 64 位 x86-64 上是 LLP64,因此 intlong int 在两者上都是 32 位的,并且只有 long long int 和指针在 Windows 上是 64 位的。只有指针的大小不同;long long int 在 32 位和 64 位 Windows 上都是 64 位。)

    所以,“字长”确实是一个模糊的概念,根本无法捕捉到情况的复杂性。

    即使是常见的硬件架构,如 x86 和 x86-64(Intel 和 AMD),也有一些不同大小的寄存器。特别是,SSE xmm 寄存器(通过 SIMD/单指令进行整数和浮点运算,多数据操作)是 128 位的,AVX 将这些寄存器扩展到 256 位,AVX512 扩展到 512 位。 (当分配动态内存以用于与此类寄存器对应的类型时,您甚至不能依赖malloc() 在所有系统上提供足够对齐的内存,而必须使用posix_memalign()&lt;xmmintrin.h&gt; 中的_mm_malloc() 等代替。静态变量和局部变量当然会充分对齐;只是 malloc() 无法确保充分对齐,因为这些是所谓的 向量类型,而 C 标准表示它们可能需要更大的对齐比正常的动态内存管理提供的。)

    在 Linux 上,最有用的“字长”是 long int(等效于 long)的大小,因为它与通用整数寄存器大小匹配最佳,并且是最佳类型(跨所有硬件架构,在 Linux 中运行时),例如多分支位数组,因为基本的二进制操作(和、或、异或、位移)在 unsigned long/unsigned long int 类型上最有效。 (但请记住,这仅适用于 Linux,一般情况下并非如此,例如在 Windows 上。)

    在实际应用中,您应该包含&lt;stdint.h&gt;&lt;inttypes.h&gt;,并使用精确宽度类型(intN_t、uintN_t)结构成员和可能的 API(外部公开的函数 - 尽管您绝对应该使用 size_t 来表示内存大小和计数,而 intptr_t/uintptr_t 用于整数类型,在转换为整数类型和返回时保留指针值到原始指针类型),以及用于局部变量和内部函数参数的快速最小宽度类型(int_fastN_t、uint_fastN_t);对于 8、16、32、64 中的 N

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-22
      • 1970-01-01
      • 2022-12-01
      • 2010-10-17
      • 1970-01-01
      • 1970-01-01
      • 2020-07-17
      相关资源
      最近更新 更多