Q:整数区分出有符号数和无符号数的意义是什么?
A:整数有正数也有负数,有符号数为了在基本数据类型大小之内既表达正负,又表达数值,才不至于在表达正负依赖其他基本类型或复杂类型协助,失去C语言简洁的特性。
无符号数相当于只有正数,在常规意义数值分析上最大挖掘和表达类型内存空间的范围。
Q:浮点数为何没有有符号数和无符号数的称呼?
A: 浮点数一般采用IEEE754 去表达,已有符号位,不需有符号和无符号特别称呼。
Q: CPU如何识别有符号和无符号数?
A: 其实CPU根本不识别有符号数和无符号数,它只是当做数。问题来了,代码中有signed和unsigned区别的数,CPU怎么能正确处理?
int i = 1;
unsigned u = 2;
printf("%d %d\n", i, u);
movl $0x1, %esi
movl $0x2, %edx
编译器都是用movl指令,似乎没看到int和unsigned.
int i = -1;
unsigned u = -1;
printf("%d %d\n", i, u);
movl $0xffffffff, %esi
movl $0xffffffff, %edx
编译器把-1转换成0xffffffff, CPU还是不知道int和unsigned是何物,上面的代码编译器确认只有printf使用i和u, 直接填入数值即可。
Q: char/unsigned char和int转换的代码可能让CPU迷惑,看看有什么不同。
A:
int char_to_int(signed char c)
{
return c;
}
pushq %rbp
movq %rsp, %rbp
movb %dil, %al
movb %al, -0x1(%rbp)
movsbl -0x1(%rbp), %eax
popq %rbp
retq
注: g++编译, 默认clang会优化。
signed char转换成int: movsbl指令会扩展符号位,从char到int.
int uchar_to_int(unsigned char c)
{
return c;
}
pushq %rbp
movq %rsp, %rbp
movb %dil, %al
movb %al, -0x1(%rbp)
movzbl -0x1(%rbp), %eax
popq %rbp
retq
注: g++编译, 默认clang会优化。
unsigned char转换成int: movzbl指令高位扩展为0(即不扩展符号位),从char到int.
movsbl和movzbl和有符号数无符号数挂上钩了,虽然也是编译器提供的指令!
作者: 陈曦
环境: MacOS 10.14.5 (Intel i5)
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.6.0
Linux 3.16.83 (Ubuntu)
转载请注明出处