这一集视频我们来看一下第二章的第一节。从这一集视频开始,我决定只讲代码和我认为需要挑出来讲解的难点/细节,对于难点和细节,我决定以提出问题和解决问题的形式来呈现。关于代码,基本只讲书上出现过的代码,实在有需要我再自己补充代码。毕竟基础知识的话,我觉得书上写的已经足够详细了,我再复述一遍没什么太多的意义,所以,大家看书的话,常看常新呀,总之就是一定要常看。

因为代码是更加直观的东西,并且,我们最终都是要去实际地写代码的。所以,我这里将着重去讲解书上出现的每一处代码,我认为能够理解代码,并且把这些代码实际应用到我们实际的项目中去,这才是真正有意义的事情。

如果我们能做到完全理解书上的这些代码,做到看到这些代码时心中有底,我觉得那就是胜利。同时,如果习题里面有涉及代码的部分,我们也不会错过。

尽量做到:一切都在代码中。这样,如果有人问,你读过这本书吗?我们可以很有底气地说,读过,毕竟,代码全都掌握了,难道还不算读过吗?

这里还要额外多说一点,就是,从这一章开始,我在视频中演示代码所使用的编辑器将换到 neovim + neovide 这样一个组合,然后,在 Windows 平台下,我会使用 pwsh 也就是 powershell 脚本来进行自动化编译和运行,而在 Linux 中,我将使用 shell 脚本来自动化编译和运行。当然,构建工具使用的肯定是 cmake。

那么,就直接看代码吧。

说明:代码的命名规范依然以英文原版书中出现的代码的页码为指导原则。

Part1

英文原书 p32,

 1#include <iostream>
 2
 3int main()
 4{
 5    int i = 1;
 6    int j = 2;
 7    i = i + j;
 8    std::cout << i << std::endl;
 9
10    return 0;
11}

个人对英文原书 32 页补充代码,custom_p32.cpp,

 1#include <iostream>
 2
 3int main()
 4{
 5    // bool 类型,通常大小为 1 个字节
 6    bool boolean = true;
 7    std::cout << "bool: " << boolean << " (size: " << sizeof(boolean) << " bytes)" << std::endl;
 8
 9    // char 类型,8 bits
10    char character = 'A';
11    std::cout << "char: " << character << " (size: " << sizeof(character) << " bytes)" << std::endl;
12
13    // wchar_t 类型,宽字符,16 bits 或 32 bits,取决于平台
14    wchar_t wide_character = L'A';
15    std::wcout << "wchar_t: " << wide_character << " (size: " << sizeof(wide_character) << " bytes)" << std::endl;
16
17    // char16_t 类型,16 bits Unicode 字符
18    char16_t unicode_16 = u'A';
19    std::wcout << "char16_t: " << static_cast<wchar_t>(unicode_16) << " (size: " << sizeof(unicode_16) << " bytes)" << std::endl;
20
21    // char32_t 类型,32 bits Unicode 字符
22    char32_t unicode_32 = U'A';
23    std::wcout << "char32_t: " << static_cast<wchar_t>(unicode_32) << " (size: " << sizeof(unicode_32) << " bytes)" << std::endl;
24
25    // short 整数类型,16 bits
26    short short_integer = 16;
27    std::cout << "short: " << short_integer << " (size: " << sizeof(short_integer) << " bytes)" << std::endl;
28
29    // int 整数类型,通常至少为 32 bits,但某些系统上可能为 16 bits
30    int integer = 26;
31    std::cout << "int: " << integer << " (size: " << sizeof(integer) << " bytes)" << std::endl;
32
33    // long 整数类型,通常为 32 bits
34    long long_integer = 36;
35    std::cout << "long: " << long_integer << " (size: " << sizeof(long_integer) << " bytes)" << std::endl;
36
37    // long long 整数类型,64 bits
38    long long long_long_integer = 46LL;
39    std::cout << "long long: " << long_long_integer << " (size: " << sizeof(long_long_integer) << " bytes)" << std::endl;
40
41    // float 单精度浮点数,精度为 6 位有效数字
42    float single_precision = 3.1f;
43    std::cout << "float: " << single_precision << " (size: " << sizeof(single_precision) << " bytes, precision: " << FLT_DIG << " significant digits)" << std::endl;
44
45    // double 双精度浮点数,精度为 10 位有效数字
46    double double_precision = 3.14;
47    std::cout << "double: " << double_precision << " (size: " << sizeof(double_precision) << " bytes, precision: " << DBL_DIG << " significant digits)" << std::endl;
48
49    // long double 扩展精度浮点数,通常与 double 相同,但某些系统上可能有更高精度
50    long double extended_precision = 3.1415L;
51    std::cout << "long double: " << extended_precision << " (size: " << sizeof(extended_precision) << " bytes, precision: " << LDBL_DIG << " significant digits)" << std::endl;
52
53    return 0;
54}

关于这些基本类型,如果有时间的话,推荐大家去看《深入理解计算机系统(第三版)》这本书,英文名是:Computer Systems: A Programmer’s Perspective (3rd Edition),也就是大名鼎鼎的 CSAPP。就拿浮点数来说,这个是我当时完整看过的,所以能够安心地给出评价,那就是如果你想理解浮点数真正的构造及原理,那么,可以抽空看一下这本书

那么,如果仅仅停留在本书需要理解的程度,那么,我们就像上面这样写几行代码就可以了解怎么去使用了,

使用微软的 MSVC 编译器运行的结果如下,

 1bool: 1 (size: 1 bytes)
 2char: A (size: 1 bytes)
 3wchar_t: A (size: 2 bytes)
 4char16_t: A (size: 2 bytes)
 5char32_t: A (size: 4 bytes)
 6short: 16 (size: 2 bytes)
 7int: 26 (size: 4 bytes)
 8long: 36 (size: 4 bytes)
 9long long: 46 (size: 8 bytes)
10float: 3.1 (size: 4 bytes, precision: 6 significant digits)
11double: 3.14 (size: 8 bytes, precision: 15 significant digits)
12long double: 3.1415 (size: 8 bytes, precision: 15 significant digits)

这里为什么有些尺寸感觉和书上有差异呢?因为书上写的是标准规定的只是最小尺寸,然后在此基础上编译器可以自由发挥。

Part2 类型转换

p35,

 1#include <iostream>
 2
 3int main()
 4{
 5    bool b = 42; // b is true
 6    std::cout << b << std::endl;
 7    int i = b; // i has value 1
 8    std::cout << i << std::endl;
 9    i = 3.14; // i has value 3
10    std::cout << i << std::endl;
11    double pi = i; // pi has value 3.0
12    std::cout << pi << std::endl;
13    unsigned char c = -1; // assuming 8-bit chars, c has value 255
14    std::cout << c << std::endl;
15    std::cout << static_cast<int>(c) << std::endl;
16    signed char c2 = 256; // assuming 8-bit chars, the value of c2 is undefined
17    std::cout << c2 << std::endl;
18    std::cout << static_cast<int>(c2) << std::endl;
19    return 0;
20}

p36_1,

 1#include <iostream>
 2
 3int main()
 4{
 5    int i = 42;
 6    std::cout << i << std::endl;
 7    if (i) // condition will evaluate as true
 8        i = 0;
 9    std::cout << i << std::endl;
10    return 0;
11}

p36_2,

 1#include <iostream>
 2
 3int main()
 4{
 5    unsigned u = 10;
 6    int i = -42;
 7    std::cout << i + i << std::endl; // prints -84
 8    std::cout << u + i << std::endl; // if 32-bit ints, prints 4294967264
 9
10    return 0;
11}

这里书上的解释有点问题,英文原版里面是让我们去看上面的案例,这里中文翻译多给了一些解释,但是这个解释不太能够让人理解,我们还是按照上面的取模的解释来。而对于给负数取模,我们可以把其想象成反方向拨动时钟,然后,从 0 到指针之间的距离就是我们所求的取模后的余数。

p37_01,

 1#include <iostream>
 2
 3int main()
 4{
 5    unsigned u1 = 42, u2 = 10;
 6    std::cout << u1 - u2 << std::endl; // ok: result is 32
 7    std::cout << u2 - u1 << std::endl; // ok: but the result will wrap around
 8
 9    return 0;
10}

p37_02,

 1// 这里需要看一下中文版 p11 也的练习题第 2 题
 2#include <iostream>
 3
 4int main(int argc, char *argv[])
 5{
 6    for (int i = 10; i >= 0; --i)
 7        std::cout << i << std::endl;
 8
 9    return 0;
10}

按:这里可以到 1.4.1 节(英文 p13)的练习那里去看一下。

p37_03,

 1#include <iostream>
 2
 3int main()
 4{
 5    /*
 6    // WRONG: u can never be less than 0; the condition will always succeed
 7    for (unsigned u = 10; u >= 0; --u)
 8        std::cout << u << std::endl;
 9    */
10    return 0;
11}

p37_04,

 1#include <iostream>
 2
 3int main()
 4{
 5    unsigned u = 11; // start the loop one past the first element we want to print
 6    while (u > 0)
 7    {
 8        --u; // decrement first, so that the last iteration will print 0
 9        std::cout << u << std::endl;
10    }
11
12    return 0;
13}

Part3 字面值常量

p38_01,

 1#include <iostream>
 2
 3int main()
 4{
 5    int a = 20;   // 十进制
 6    int b = 024;  // 八进制
 7    int c = 0x14; // 十六进制
 8    std::cout << a << ", " << b << ", " << c << std::endl;
 9    return 0;
10}

p38_02,

 1#include <iostream>
 2
 3int main()
 4{
 5    double a = 3.14159;
 6    double b = 3.14159E0;
 7    double c = 0.;
 8    double d = 0e0;
 9    double e = .001;
10    std::cout << a << ", " << b << ", " << c << ", " << d << ", " << e << std::endl;
11    return 0;
12}

p39_01,

 1#include <iostream>
 2#include <string>
 3
 4int main()
 5{
 6    char a = 'a';
 7    std::string b = "Hello World!";
 8    std::cout << a << ", " << b << std::endl;
 9    return 0;
10}

p39_02,

1#include <iostream>
2
3int main()
4{
5    // multiline string literal
6    std::cout << "a really, really long string literal "
7                 "that spans two lines" << std::endl;
8    return 0;
9}

p39_03,

 1#include <cstdio>
 2#include <iostream>
 3
 4int main()
 5{
 6    std::cout << "Hello\nWorld" << std::endl;
 7    std::cout << "Name\tAge" << std::endl;
 8    std::cout << "\a" << std::endl;
 9    std::cout << "Hello\vWorld" << std::endl;
10    std::cout << "Helloo\b World" << std::endl;
11    std::cout << "He said, \"Hello!\"" << std::endl;
12    std::cout << "C:\\Program Files" << std::endl;
13    std::cout << "What\?" << std::endl;
14    std::cout << "It\'s a cat" << std::endl;
15    std::cout << "Hello\rWorld" << std::endl;
16    std::cout << "Hello\fWorld" << std::endl;
17    getchar();
18    return 0;
19}

p39_04,

1#include <iostream>
2
3int main()
4{
5    std::cout << '\n';      // prints a newline
6    std::cout << "\tHi!\n"; // prints a tab followd by "Hi!" and a newline
7    return 0;
8}

p39_05,

 1#include <iostream>
 2
 3int main()
 4{
 5    std::cout << "\7";            // 在一些环境下会发出提示音,和 \a 相同
 6    std::cout << "Hello\12World"; // 输出:
 7                                  // Hello
 8                                  // World
 9                                  // 实际效果等同于 \n
10
11    std::cout << "Hello\40World"; // 输出:Hello World (插入一个空格)
12
13    char str[] = "Hello\0World";
14    std::cout << str; // 输出:Hello (由于\0表示字符串结束,World部分不会被输出)
15
16    std::cout << "\115"; // 输出:M
17
18    std::cout << "\x4d"; // 输出:M
19    return 0;
20}

p40_01,

1#include <iostream>
2
3int main()
4{
5    std::cout << "Hi \x4dO\115!\n"; // prints Hi MOM! followed by a newline
6    std::cout << '\115' << '\n';    // prints M followed by a newline
7    return 0;
8}

p40_02,

 1#include <iostream>
 2
 3int main()
 4{
 5    // 1. L'a' - wide character literal (wchar_t)
 6    wchar_t wideChar = L'a';
 7    std::wcout << L"Wide character literal: " << wideChar << std::endl;
 8
 9    // 2. u8"hi!" - UTF-8 string literal
10    const char *utf8String = u8"hi!";
11    std::cout << "UTF-8 string literal: " << utf8String << std::endl;
12
13    // 3. 42ULL - unsigned long long literal
14    unsigned long long ullValue = 42ULL;
15    std::cout << "Unsigned long long literal: " << ullValue << std::endl;
16
17    // 4. 1E-3F - single-precision floating-point literal (float)
18    float floatValue = 1E-3F;
19    std::cout << "Single-precision floating-point literal: " << floatValue << std::endl;
20
21    // 5. 3.14159L - extended-precision floating-point literal (long double)
22    long double longDoubleValue = 3.14159L;
23    std::cout << "Extended-precision floating-point literal: " << longDoubleValue << std::endl;
24
25    return 0;
26}

p41,

1#include <iostream>
2
3int main() {
4
5    bool test = false;
6    std::cout << test << std::endl;
7    return 0;
8}