c - "C variable type sizes are machine dependent."是真的吗?有符号和无符号数;

标签 c assembly types

有人告诉我 C 类型是机器相关的。今天想验证一下。

void legacyTypes()
{
    /* character types */
    char k_char = 'a';

        //Signedness --> signed & unsigned
        signed char k_char_s = 'a';
        unsigned char k_char_u = 'a';

    /* integer types */
    int k_int = 1; /* Same as "signed int" */

        //Signedness --> signed & unsigned
        signed int k_int_s = -2;
        unsigned int k_int_u = 3;

        //Size --> short, _____,  long, long long
        short int k_s_int = 4;
        long int k_l_int = 5;
        long long int k_ll_int = 6;

    /* real number types */
        float k_float = 7;
        double k_double = 8;
}

我使用 minGW C 编译器在 32 位机器 上编译了它

_legacyTypes:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $48, %esp
    movb    $97, -1(%ebp)  # char
    movb    $97, -2(%ebp)  # signed char
    movb    $97, -3(%ebp)  # unsigned char
    movl    $1, -8(%ebp)    # int
    movl    $-2, -12(%ebp)# signed int 
    movl    $3, -16(%ebp) # unsigned int
    movw    $4, -18(%ebp) # short int
    movl    $5, -24(%ebp) # long int
    movl    $6, -32(%ebp) # long long int
    movl    $0, -28(%ebp) 
    movl    $0x40e00000, %eax
    movl    %eax, -36(%ebp)
    fldl    LC2
    fstpl   -48(%ebp)
    leave
    ret

我在 GCC (linux) 上的 64 位处理器 (Intel Core 2 Duo) 上编译了相同的代码

legacyTypes:
.LFB2:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movb    $97, -1(%rbp) # char
    movb    $97, -2(%rbp) # signed char
    movb    $97, -3(%rbp) # unsigned char
    movl    $1, -12(%rbp) # int
    movl    $-2, -16(%rbp)# signed int 
    movl    $3, -20(%rbp) # unsigned int
    movw    $4, -6(%rbp)   # short int
    movq    $5, -32(%rbp) # long int
    movq    $6, -40(%rbp) # long long int
    movl    $0x40e00000, %eax
    movl    %eax, -24(%rbp)
    movabsq $4620693217682128896, %rax
    movq    %rax, -48(%rbp)
    leave
    ret

观察

  • char, signed char, unsigned char, int, unsigned int, signed int, short int, unsigned short int, signed short int 都占用同一个序号。 32 位和 64 位处理器上的字节数。

  • 唯一的变化是 long intlong long int 这两个在 32 位机器和 64 位机器上都占用 32 位在 64 位机器上。

  • 还有指针,在 32 位 CPU 上采用 32 位,在 64 位 CPU 上采用 64 位。

问题:

  • 我不能说,书上说的是错的。但我在这里遗漏了一些东西。 “变量类型依赖于机器是什么意思?”
  • 如您所见,无符号数和有符号数的指令之间没有区别。那么为什么两者可以寻址的数字范围不同呢?
  • 我正在阅读 How to maintain fixed size of C variable types over different machines?我不明白问题的目的或他们的答案。什么保持固定大小?他们都是一样的。我不明白这些答案如何确保大小相同。

编辑:

难道不可能在不同的机器上提供相同的尺寸吗?我的意思是,如何在 64 位和 32 位机器上保持相同的指针大小?

最佳答案

有更多的平台,其中一些是 16 位甚至 8 位的!在这些上,您会观察到上述所有类型的尺寸差异更大。

相同基本类型的有符号和无符号版本在任何平台上占用相同数量的字节,但是它们的数字范围不同,因为对于有符号数字,有符号和无符号领域共享相同范围的可能值。

例如16 位有符号整数的值可以从 -32767(或在许多平台上为 -32768)到 32767。相同大小的无符号整数在 0 到 65535 范围内。

在此之后,希望您能更好地理解所提到问题的要点。基本上,如果你编写一个程序假设例如您的 signed int 变量将能够保存值 2*10^9(20 亿),您的程序不可移植,因为在某些平台(16 位及以下)上,此值会导致溢出,导致无声且难以执行发现错误。所以例如在 16 位平台上,您需要#define 将您的整数设置为long 以避免溢出。这是一个简单的示例,可能不适用于所有平台,但我希望它能给您一个基本的概念。

平台之间存在所有这些差异的原因是,在 C 标准化时,已经有许多 C 编译器在大量不同平台上使用,因此为了向后兼容,所有这些变体都必须被接受为有效。

关于c - "C variable type sizes are machine dependent."是真的吗?有符号和无符号数;,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2533319/

相关文章:

c - 使用数组存储引脚位

c - 解析堆栈和寄存器(EBP、EIP、ESP)并找出与每个帧相关的函数

c - 为什么 gcc 会创建冗余的汇编代码?

assembly - 了解近调用指令编码

haskell - 是否可以在 Haskell 中否定类型参数约束?

haskell - 在 Haskell 中定义对布什数据类型的相等运算

c - 尝试计算C中字符串中有多少个字符

c - 如何仅使用二元运算符来划分有符号整数?

arrays - Julia 类型内的数组

c - 为什么 '+' 符号不能与 printf 一起用于无符号值?