第一章 开始
CL 编译器选项
/EHsc
https://learn.microsoft.com/zh-cn/cpp/build/reference/eh-exception-handling-model?view=msvc-170
/EHsc 是 /EHs 和 /EHc 两个参数的组合:
- /EHs:启用标准 C++ 栈展开。只捕获标准 C++ 异常(不会把结构化异常 SEH 当作 C++ 异常捕获)。
- /EHc:与 /EHs 一起使用时,编译器假定声明为 extern "C" 的函数绝不会 throw(引发)C++ 异常。与 /EHa 一起使用时(即 /EHca 等同于 /EHa),没有效果。如果未指定 /EHs 或 /EHa,则忽略 /EHc。
/W4
https://learn.microsoft.com/zh-cn/cpp/build/reference/compiler-option-warning-level?view=msvc-170
- 显示 1 级、2 级和 3 级警告,以及默认情况下未关闭的所有 4 级(信息性)警告。 建议您使用此选项来提供链接形式的警告。 对于新项目,最好在所有编译中使用 /W4。 此选项有助于确保尽可能减少难以发现的代码缺陷。
原码 / 反码 / 补码是什么
参考:https://segmentfault.com/a/1190000021511009
原码
原码是一种计算机中对数字的二进制定点表示法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为 0,负数该位为 1(0 有两种表示:+0 和 -0),其余位表示数值的大小。举个例子,我们用 8 位二进制表示一个数,+12 的原码为 00001100,-12 的原码就是 10001100。
反码
反码是一种计算机中对数字的二进制定点表示法。反码表示法在正数的基础上,对负数按位取反(符号位不变)。举个例子,我们用 8 位二进制表示一个数,+12 的反码为 00001100,-12 的反码就是 11110011。
补码
补码是一种用二进制表示有符号数的方法。正数和 0 的补码就是该数字本身。负数的补码则是将其对应正数按位取反再加 1。补码系统的最大优点是可以在加法或减法处理中,不需因为数字的正负而使用不同的计算方式。只要一种加法电路就可以处理各种有符号数加法,而且减法可以用一个数加上另一个数的补码来表示,因此只要有加法电路和补码电路即可以完成各种有符号数加法和减法,在电路设计上相当方便。

例如6 + (-3) 以补码形式的计算过程如下:
| 十进制 | 原码 | 反码 | 补码 |
|---|---|---|---|
| 6 | 0000 0110 | 0000 0110 | 0000 0110 |
| -3 | 1000 0011 | 1111 1100 | 1111 1101 |
6 - 3 ==> 6 + (-3)
0000 0110 // 6的补码
+ 1111 1101 // -3的补码
----------------------
0000 0011 // 3的补码
有符号负数到无符号转换
拿整数(32位)作例子,假如要将-5赋值给一个无符号数。
#include <iostream>
int main() {
unsigned int a = -5;
std::cout << a << std::endl;
return 0;
}
有两种计算方法:
取模
对 2^32 做数学意义上的取模(结果取非负值):
(-5) mod 2^32 = 4294967296 - 5 = 4294967291
注意这里说的是数学上的取模,不是 C++ 的 % 运算符(C++ 中 % 向零截断,-5 % n 的结果仍是负数)。
计算补码
- 首先按 32 位整数计算 -5 的补码:
11111111 11111111 11111111 11111011 - 解释为无符号数:接着,这个补码被赋给无符号变量。在无符号变量中,所有位都用来表示数值,包括原本表示负数的最高位。因此,这个补码被直接当作一个大的正数来解释。
- 转换为十进制:将这个二进制数转换为十进制:
4294967291