第二章、信息的表示和处理

背景

在实际编程中,依然对有些数值的处理和变换比较模糊,在看csapp的时候发现里面的论述很详细,常规问题不在此赘述,这里主要是记录大部分人的知识点盲区。

信息存储

  • 大小端
    计算的数据存储分为大小端两种,lscpu可以看到本地的机器的大小端数值,大小端的颗粒度是字节(也就是8bit)这个要记清楚,当做类型强制cast的时候一定要留心这个问题, 寄存器里没有这个问题,比如存在rax里面的数值,最后取出eax的结果。
#include 
int main()
{
    int a = 234153;
    int b = a + 1;
    __asm__("movq   $123456789000, %rbx"); 
    __asm__("movl   %ebx, -4(%rbp)"); 
    std::cout<<a<<std::endl; // $-1097262584
    return 0;
}
// $123456789000 = 0x1C BE 99 1A 08
// $-1097262584 = 0xBE 99 1A 08
  • 移位运算
    主要记住在c/c++中的右移是算术右移,不符合常规认知,简单说比如右移3位[k,0,0,1,0] -> [k,k,k,k,0,0,1,0]

整数表示

  • 表示方法
    整数分为无符号和有符号,无符号就是原码逻辑,有符号就是补码逻辑(至于补码如何计算自己查书),也就是-1是0xfffffff。常量默认是是int, 其他数值类型需要自己指定:123(int), 123u(unsigned int), 123ul(unsigned long), 目前short没有,听说只有部分编译器支持后缀"s"。
  • 无符号和有符号混合计算
    无符号和有符号混合计算,统一转给无符号处理,一般加减乘除不会影响,但是><这种大小判断符号就会影响很大
  • b无符号与有符号转换
    这个static_cast或者默认转换,bit不变。这个会导致很多奇怪的bug,比如int8->uint18, 范围从-128~127到0-255,这样会导致负数部分会被翻译为奇怪的正数。
// it's right
if(0u < -1) std::cout<<"hello"<<std::endl;
  • bit扩展
    int8->int16->int32->int64在高位补上最高位,[k,0,0,1,0] -> [k,k,k,k,0,0,1,0]
    uint8->uint16->uint32->uint64在高位补上0,[k,0,0,1,0] -> [0,0,0,k,0,0,1,0]
    至于为啥这样搞?书里有证明
  • bit截断
    无符号和有符号都一样, bit都是这样:[k,k,k,k,0,0,1,0] -> [k,0,0,1,0]
  • 整数溢出
    整数不像小数一样,ALU并不会对值进行溢出判断,溢出的结果就截断和上面一样,所以不会有异常值爆出,这里需要用户自己去根据计算规则推出溢出的判断方式,书中给了加法的结果判断,这里不再详述。

浮点数表示

参考:https://blog.csdn.net/feng__shuai/article/details/79111084

你可能感兴趣的:(计算机基础知识,c++)