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
- {
- printf("-1 < 0\n");
- }
- else{
- printf("-1 > 0\n"); ##############
- }
无符号数的加法w
1. 溢出:无符号数溢出,可以通过smod256 = 4
- #include
-
- int main()
- {
- unsigned char a=130;
- printf("%u\n",(unsigned char)(a+a)); //4
- return 0;
- }
2. mod数的逆: 2 w − x " role="presentation" style="position: relative;">
- #include
-
- 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