CSAPP 2.3 整数的运算

这篇博客探讨了C语言中格式化输出、类型转换和溢出行为,包括无符号整数与有符号整数的相互转换、乘法运算的溢出规则、浮点数比较、二进制运算以及整数拓展。还涉及了除法运算和符号数的非运算。文章通过实例解释了溢出后的模运算以及如何判断溢出,并展示了不同类型的变量在内存中的表示方式。
摘要由CSDN通过智能技术生成

C语言的格式化输出(仅仅是格式化输出而已,binary就是那样)

%u  unsigned int

%d  signed int

%x hex      (如果是char打印出16进制 0x xx)

    char x = -1;

    printf("x=%d = %u",(char)x, (unsigned char)x);   // -1   255     0b1111 1111

加减乘除(溢出都是mode 2^w)

无论是带符号还是不带符号,溢出都是 +/-256 (2^w)

乘法也一样,无符号数乘法直接mode 256

                      符号数乘法mode 256后,看剩下的8bit的第一位是1还是0,进程U2T(binray to two's component的转换)                                                                                                                            【非直观1】x的平方可能不是正数,比如char *char 50*50=2500mod 256 = 196 = 0b1100 0100 =-128+64+4=-60                                                                                                                                  很对规则本质都是拿binary去操作,怎么翻译是最后的事情

- 例子1: int->short的截断,直接截断binary,最后看翻译成sign还是unsign

- 例子2: char*char 溢出后截断,也是直接截断binary,最后翻译 char

- 例子3: float的数据比较大小,直接比较binray的大小,因为exponent大的不管尾数肯定也大

- 例子4: -1 = 1111 1111 肯定大于 -2  1111 1110  同样适用

- 例子5:sign < unsign, 计算机背后也是直接拿binary去比较大小,所以默认会转换为无符号数然后去比较·          

    //显式类型转换,隐式类型转换,格式化输出,底层的binary都不变,U2T T2U = I,没有数据损失
    unsigned char a = 255;
    char b=a;
    unsigned char c = b;
    printf("%u %d %d\n",a,b,c);
    //直接截断,然后翻译
    //这和 符号乘法一样,50*50=-60 char*char= mod截断后直接翻译U2T
    short x = 128; // 0000 0000 1000 0000   =0x 00  80
    char y = x;     //1000 0000 = 0x 80
    short z = y;    // 1111 1111 1000 0000  = 0x ff 80
    printf("%d %d %d\n",x,y,z);   //128 -128 -128

    int x=-1;
    unsigned  int y=0;
    if(x<y)
    {
        printf("-1 < 0\n");
    }
    else{
        printf("-1 > 0\n");   ##############
    }

无符号数的加法w

1. 溢出:无符号数溢出,可以通过s<x或者s<y来判断,溢出后 s=(x+y)mod (2^w) .比如8bit, 2^8=256, s=260mod256 = 4

#include <stdio.h>

int main()
{
    unsigned char a=130;
    printf("%u\n",(unsigned char)(a+a)); //4
    return 0;
}

2. mod数的2^w-x

#include <stdio.h>

int main()
{
    unsigned char a=100;
    unsigned char b=156;
    printf("%u\n",(unsigned char)(a+b));  //0
    return 0;
}

符号数的加法

1. 正溢出, 负溢出,正常

#include <stdio.h>

int main()
{
    //-128 ~ 127
    printf("%d\n",(char)(100+28)); // 正溢出(-256)  128 - 256 = -128
    printf("%d\n",(char)(-100-56)); // 负溢出(+256) -156 + 256 = 100
    printf("%d\n",(char)(20-30)); // -10
    return 0;
}

binary取反,就是非。带符号数的非就是 ~x = (-x-1)   ,记住1的反是-2

#include <stdio.h>

int main()
{
    //-128 ~ 127
    char x=1;                          // 0001 = 1
    printf("x=%d,~x=%d\n",x,~x); //-2  // 1110 = -8+4+2
    return 0;
}

1的非-2, -8的非是7. 至于为什么,原因就是 x+(-x)=0, 所以取反加一就是相反数

整数拓展

把一个unsigned char扩展成unsigned short,只需要在开头加零,叫zero extension 零扩展。

把signed char拓展成signed short,在开头的8位加上原来的符号位(0000 0000 或者1111 111)

#include <stdio.h>
typedef unsigned char *byte_pointer;
void show_byte(byte_pointer x, int len)
{

    for (int i = 0; i < len; i++)
    {
        printf("%x ", x[i]);
    }
    printf("\n");
}

int main()
{
    char x = -3;             // 1111 1101 = -1-2 = 1111 1111 -2
    unsigned char ux = x;    //  253 = 255-2
    short sx = x;            // 1111 1111 1111 1101 = -3 = -1-2
    unsigned short usx = ux; // 253
    printf("%d ", x);
    show_byte((byte_pointer)&x, sizeof(x)); // fd
    printf("%u ", ux);
    show_byte((byte_pointer)&ux, sizeof(ux)); // fd
    printf("%d ", sx);
    show_byte((byte_pointer)&sx, sizeof(sx)); // fd ff
    printf("%u ", usx);
    show_byte((byte_pointer)&usx, sizeof(usx)); // fd 0
    return 0;
}

有符号整数除法

连续符号拓展,这一除法之后,补的是符号位,0则补0, 1则补1

除法出来的结果是向下取整

63/8 = 7

-63/8 = -8 

表示字符串

 可以使用man ascii 查看 a 是0x61. 上述代码输出 61 62 63

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值