知识点总结
1. 逻辑运算符关系
and(与)、or(或)和xor(异或)是逻辑运算符,用于对布尔值进行操作。它们可以在不同的逻辑表达式之间进行转换。下面是and、or和xor之间的转换规则:
- and转换为or: a and b = !(a or b) (取反)
- or转换为and: a or b = !(a and b) (取反)
- xor转换为and和or: a xor b = (a and !b) or (!a and b)
2. 补码
二进制补码(Two’s complement)是一种表示有符号整数的方法。它是计算机中常用的表示负数的方式。
在二进制补码表示中,最高位(最左边的位)被用作符号位,0表示正数,1表示负数。其余位表示数值的绝对值。
二进制补码的转换规则如下
- 对于正数,其二进制补码就是其二进制表示本身。
- 对于负数,首先需要将其绝对值转换为二进制表示,然后对其进行按位取反操作(即将0变为1,将1变为0),最后再加1。例如,对于十进制数-5,其二进制补码的转换步骤如下:将5转换为二进制表示:5 = 00000101,对二进制表示按位取反:11111010,将取反后的结果加1:11111011,所以,-5的二进制补码为11111011。
使用二进制补码表示有符号整数,可以方便地进行加法和减法运算,而无需特殊处理符号位。此外,二进制补码的表示范围也比使用其他方法表示负数更广泛。
补码范围:
补码是一种表示有符号整数的方法,它使用最高位作为符号位,0表示正数,1表示负数。补码的范围取决于使用的位数。
对于n位二进制补码表示,最小的补码整数是将最高位设置为1,其余位设置为0,最大的补码整数是将所有位都设置为1。
以8位二进制补码为例,最小的补码整数是:
10000000
这个二进制数的十进制表示是-128。
最大的补码整数是:
01111111
这个二进制数的十进制表示是127。
因此,8位二进制补码表示的范围是-128到127。
对于n位二进制补码,范围可以表示为-2 ^ (n-1) 到 2 ^ (n-1)-1。
3. int 获取负数
int
类型的二进制表达式是用二进制数字表示一个整数。在C语言中,int
类型通常是有符号的,因此它使用补码表示法来表示负数。
对于有符号的int
类型,它占用固定的位数(通常是32位),其中最高位(最左边的一位)是符号位,用来表示正负。如果符号位为0,则表示该整数是正数;如果符号位为1,则表示该整数是负数。
以下是一个示例,展示了一个有符号32位int
类型的二进制表达式:
00000000 00000000 00000000 00000000 // 0
00000000 00000000 00000000 00000001 // 1
00000000 00000000 00000000 00000010 // 2
...
01111111 11111111 11111111 11111110 // 2147483646
01111111 11111111 11111111 11111111 // 2147483647 (INT_MAX)
10000000 00000000 00000000 00000000 // -2147483648 (INT_MIN)
10000000 00000000 00000000 00000001 // -2147483647
10000000 00000000 00000000 00000010 // -2147483646
...
11111111 11111111 11111111 11111110 // -2
11111111 11111111 11111111 11111111 // -1
需要注意的是,整数的二进制表达式是从右向左排列的,最右边的一位是最低位,最左边的一位是最高位。每个二进制位表示一个权值,从右向左依次为1、2、4、8、16、32、64、128、256、…,以此类推。
对于无符号的int
类型(即unsigned int
),它也占用固定的位数(通常是32位),但没有符号位,因此可以表示更大的正整数。
以上是一个简单的示例,展示了int
类型的二进制表达式。实际上,具体的二进制表达式可能会因编译器和平台的不同而有所不同。如果需要精确地了解某个特定编译器和平台上int
类型的二进制表达式,可以使用位运算或相关的工具来查看。
简单来说就是 x 的负数就是 ~x+1
4. 判断字符是否是digit
5. 正数和负数的左移和右移
在C语言中,对于正数的左移操作和右移操作,补充的是零。
正数左移:
unsigned int x = 5; // 二进制表示为 00000101
unsigned int result = x << 2; // 左移2位,移动后的结果为 00010100,等于20
正数右移:
unsigned int x = 20; // 二进制表示为 00010100
unsigned int result = x >> 2; // 右移2位,移动后的结果为 00000101,等于5
负数右移:
int x = -20; // 二进制表示为 11101100
int result = x >> 2; // 右移2位, 移动后的结果为 11111011,等于-5
对于负数的左移操作,结果是未定义的。这是因为左移操作可能导致符号位发生改变,而C语言并没有明确规定负数左移的补充规则。因此,负数的左移操作是不可靠的,应该避免使用。
6. 负数使用逻辑非
这是因为非零的值在逻辑上被视为真,而逻辑非运算符将其取反得到假的结果。
int x = -10;
int result = !x;
// result 的值为 0
7. 逻辑取反运算符有两种形式:~ 和 !。
逻辑取反运算符有两种形式:~
和 !
。
-
~
运算符是按位取反运算符,用于对一个整数的二进制表示进行按位取反操作。它将每个二进制位的值进行翻转,即0变为1,1变为0。~
运算符只适用于整数类型。 -
!
运算符是逻辑取反运算符,用于对一个表达式的逻辑值进行取反操作。如果表达式的值为真(非零),则!
运算符将其取反为假(0),如果表达式的值为假(0),则!
运算符将其取反为真(非零)。!
运算符适用于任何标量类型,包括整数、浮点数和指针类型。
以下是两种运算符的示例:
int x = 10;
int y = 0;
int result1 = ~x; // result1 的值为 -11
int result2 = !y; // result2 的值为 1
在上面的示例中,~x
对整数 x
进行按位取反操作,结果为 -11
。而 !y
对整数 y
进行逻辑取反操作,因为 y
的值为0,所以结果为1。
8. 溢出问题
例如: int的范围是
01111111 11111111 11111111 11111111 // 2147483647 (INT_MAX)
10000000 00000000 00000000 00000000 // -2147483648 (INT_MIN) == 2 ^ 31
-2 ^ 31 - ( -2 ^ 31) 会出现溢出问题
9. 浮点数
浮点数编码是一种将浮点数值转换为二进制表示的过程。在计算机中,浮点数通常使用IEEE 754标准进行编码。
IEEE 754标准定义了两种浮点数表示格式:单精度(32位)和双精度(64位)。这两种格式都包括三个部分:符号位、指数位和尾数位。
符号位用于表示浮点数的正负性,占据了编码中的第一位。0表示正数,1表示负数。
指数位用于表示浮点数的指数部分,确定浮点数的大小范围。在单精度编码中,指数位占据了接下来的8位,而在双精度编码中,指数位占据了接下来的11位。
尾数位用于表示浮点数的小数部分,确定浮点数的精度。在单精度编码中,尾数位占据了接下来的23位,而在双精度编码中,尾数位占据了接下来的52位。
通过这种编码方式,浮点数可以以二进制形式存储和计算。然而,由于浮点数编码的特殊性,可能会出现精度损失和舍入误差等问题。因此,在进行浮点数计算时,需要注意这些问题可能带来的影响。
问题合集
1. makefile
删除m32:
使用gcc -m32
编译的可执行文件无法在64位操作系统上运行。这是因为gcc -m32
选项会将代码编译为32位的目标平台,生成的可执行文件只能在32位操作系统上运行。
在64位操作系统上运行32位可执行文件需要在系统上安装相应的32位库和运行环境。如果你尝试在64位操作系统上运行32位可执行文件,可能会遇到错误,例如缺少所需的库或不兼容的系统调用。
如果你希望在64位操作系统上运行代码,你应该使用默认的gcc
命令来编译代码,而不是使用gcc -m32
选项。这样将生成适用于64位目标平台的可执行文件。
2. c文件不是cpp文件
打印函数使用# include <stdio.h>
参考答案和解析
https://zhuanlan.zhihu.com/p/106109635