Byte = 8 bits
& and 且
| or 或
~ not 非
^ xor(Exclusive-or) 异或
A^B = 1, 当 A=1或者B=1时,但不是全部都为1
^ | 0 1
---------
0 | 0 1
1 | 1 0
操作示例:
01101001 { 0, 3, 5, 6 }
76543210
01010101 { 0, 2, 4, 6 }
76543210
操作:
与位操作有些相似,不要搞混淆。
操作符:&&, ||, !
特性:
左移 x << y
将位向量x左移y个位置。
扔掉左边多余的部分。
右边空位填0
右移 x >> y
将位向量x右移y个位置。
扔掉右边多余的部分。
逻辑右移:
左边空位填0
算术右移:
左边空位填充符号位
示例:
Argument x : 10100010
x << 3 : 00010000
Log. x >> 2 : 00101000
Arith. x >> 2 : 11101000
补码:表示有符号数的最常用的方式,有符号数还有其他表示方式,但是补码是最常用的方式。
无符号值
UMin = 0 (000…0)
Umax = 2^w -1 (111…1)
二进制补码
TMin = -2^(w-1) (100…0)
TMax = 2^(w-1) -1 (011…1)
-1 : 111…1
规律
|TMin| = TMax + 1
UMax = 2 * TMax + 1
c程序
limits.h 定义了一些边界值。
#include
ULONG_MAX
LONG_MAX
LONG_MIN
B: Binary 二进制,U: Unsigned 无符号, T: Two’s Complement 二进制补码
无符号与有符号的转换映射:
4位为例,符号位为1时:符号位的值 + 其他位的值
二进制补码:-2^3 + 其他位的值 = -8 + 其他位的值
无符号:2^3 + 其他位的值 = 8 + 其他位的值
无符号 - 二进制补码 = 8 + 其他位的值 - (-8 + 其他位的值) = 16 = 2^4
U
表示:0U, 123123U转换:
int tx, ty;
unsigned ux, uy;
tx = (int)ux;
uy = (unsigned) ty;
ty = ux; // 无符号赋值给有符号
uy = ty;
常量1 常量2 比较结果 结果类型
0 0U == unsigned
-1 0 < signed
-1 0U > unsigned
2147483647 -2147483647-1 > signed
2147483647U -2147483647-1 < unsigned
-1 -2 > signed
(unsigned)-1 -2 > unsigned
2147483647 2147483648U > unsigned
2147483647 (int)2147483648U > signed
结论:无符号和有符号的运算,有符号转化为无符号进行运算和比较,结果为无符号。
代码验证结论:
#include
void main() {
int x = -7;
unsigned int ux = 3;
if (x > ux) {
printf("signed -7 > unsigned 3");
}
}
// output:
// signed -7 > unsigned 3
前面填充数字。
结果不会改变。
无符号
拓展字段用0填充。
有符号
拓展字段用符号位填充。
short int x = 15213;
int ix = (int)x;
short int y = -15213;
int iy = (int)y;
x: 15213, 00111011 01101101
ix: 15213, 00000000 00000000 00111011 01101101
y: -15213 11000100 10010011
iy: -15213, 11111111 11111111 11000100 10010011
截取前面的数字。
对于小数值结果不会改变,对于大数值结果可能会改变。
无符号
直接截取,相当于进行模运算:x mod 2^k
有符号
前面的符号位被截取。
类似于模运算。
#include
void main() {
int x = 53191;
short int ix = (int)x;
int y = -53191;
short iy = (int)y;
printf("x: decimal=%d,Hex=%x, ",x,x);
printfBinary(x);
printf("ix: decimal=%d,Hex=%x, ",ix,ix);
printfBinary(ix);
printf("y: decimal=%d,Hex=%x, ",y,y);
printfBinary(y);
printf("iy: decimal=%d,Hex=%x, ",iy,iy);
printfBinary(iy);
}
//输出一个数的二进制
printfBinary(int num,int w){
unsigned mask;
sscanf_s("%d", &num);
mask = 1u << 31;
for(;mask;mask>>=1){
printf("%d", num&mask?1:0);
}
printf("\n");
}
// output
// x: decimal=53191 ,Hex=cfc7 , 0000000000000000 1100111111000111
// ix: decimal=-12345,Hex=ffffcfc7, 1111111111111111 1100111111000111
// y: decimal=-53191,Hex=ffff3039, 1111111111111111 0011000000111001
// iy: decimal=12345 ,Hex=3039 , 0000000000000000 0011000000111001
《深入理解计算机系统》学习笔记 - 第一课 - 课程简介
《深入理解计算机系统》学习笔记 - 第二课 - 位,字节和整型
《深入理解计算机系统》学习笔记 - 第三课 - 位,字节和整型
《深入理解计算机系统》学习笔记 - 第四课 - 浮点数
《深入理解计算机系统》学习笔记 - 第四课 - 机器级别的程序