C中变量的内存表示和值之间的关系是什么?

What is the relationship between memory representation and value of a variable in C?

在 C 中,确实是:

[8-bit] signed char: -127 to 127
[8-bit] unsigned char: 0 to 255

但是内存中到底发生了什么? signed char是用补码表示的,unsigned char是没有具体表示的(即11111111的序列)吗?

可执行文件如何跟踪它正在读取的变量类型,以确定 CPU 寄存器中的值是否被解释为二进制补码?是否有一些元数据将变量名称与其类型相关联?

谢谢!

数字的内部表示不是C语言的一部分,它是机器本身架构的一个特征。大多数实现使用 2 的补码,因为它使加法和减法成为相同的二进制运算(有符号和无符号运算相同)。

仅供参考,几乎所有现有 CPU 硬件都使用二进制补码,因此大多数编程语言也这样做是有道理的。

没有元数据。最终执行是由底层硬件完成的,因为编译器在对这些类型进行某些操作时使用不同的指令。当你比较装配时,它会变得更加明显。

void test1()
{
  char p = 0;
  p += 3;
}

void test2()
{
  unsigned char p = 0;
  p += 3;
}

您在这里看到的是编译器根据上面发布的源代码编译的指令。编译时没有优化 -O0 这是 clang 3.7 创建的程序集。如果您不熟悉它们,您可以忽略大部分说明。继续关注 movsxmovzx。这两条指令使内存位置的处理方式有所不同。

test1():                              # Instructions for test1
    push    rbp
    mov rbp, rsp
    mov byte ptr [rbp - 1], 0
    movsx   eax, byte ptr [rbp - 1]   <-- Move byte to word with sign-extension
    add eax, 3
    mov cl, al
    mov byte ptr [rbp - 1], cl
    pop rbp
    ret

test2():                              # Instructions for test2
    push    rbp
    mov rbp, rsp
    mov byte ptr [rbp - 1], 0
    movzx   eax, byte ptr [rbp - 1]   <-- Move byte to word with zero-extension
    add eax, 3
    mov cl, al
    mov byte ptr [rbp - 1], cl
    pop rbp
    ret

C 是一种强类型语言。记忆的解释完全由上下文决定。也就是说,类型在编译时是已知的(在动态调度的情况下足够好)并且编译器提前做出所有决定。为了性能,运行时检查减少到最低限度(在 C 中到 none,除非您手动实现动态调度或 RTTI)。

在 C(和 C++)中,您可以轻松地以不同方式解释相同的内存位置,您所要做的就是获取指向它的指针并将其转换为不同的类型。如果您不知道自己在做什么,那将非常不安全。