diff --git a/404.html b/404.html index f7f1671..07a4548 100644 --- a/404.html +++ b/404.html @@ -20,7 +20,7 @@
- + \ No newline at end of file diff --git a/index.html b/index.html index a0d6637..cfb10e0 100644 --- a/index.html +++ b/index.html @@ -22,8 +22,8 @@ -
Skip to content

许大仙同学

『这个世纪疯狂,没人性,腐败;你却一直清醒,温柔,一尘不染。』

许大仙

Released under the MIT License.

- +
Skip to content

许大仙同学

『这个世纪疯狂,没人性,腐败;你却一直清醒,温柔,一尘不染。』

许大仙

Released under the MIT License.

+ \ No newline at end of file diff --git a/notes/01_c-basic/00_xdx/index.html b/notes/01_c-basic/00_xdx/index.html index 3adbb33..130b456 100644 --- a/notes/01_c-basic/00_xdx/index.html +++ b/notes/01_c-basic/00_xdx/index.html @@ -22,7 +22,7 @@ -
Skip to content

IMPORTANT

  • ① C 语言是一门面向过程编译型编程语言,其最大特点在于 运行速度极快,仅次于汇编语言,这使得 C 语言在需要高性能的场景中得到广泛应用,如:操作系统、硬件驱动程序和嵌入式系统。然而,开发效率较低也是 C 语言的一大特点,程序员需要手动管理内存和处理低级别的操作,这对编程能力要求较高。
  • ② C 语言不仅仅是一门编程语言,更是计算机行业的核心语言。它是计算机专业的基础课程,无论是操作系统的构建、硬件驱动的开发,还是数据库系统的实现,都离不开 C 语言的支持。学习 C 语言 不仅是掌握编程技能的必经之路,也是深入理解计算机底层原理的关键。如果忽视了 C 语言的学习,将难以深入理解计算机系统的工作原理,也很难在计算机行业中取得长远的发展。

NOTE

总结就是一句话:C 语言重要(赞),很重要(大赞),非常重要(非常赞),绝对重要(无敌赞),史无前例的重要(一赞到底)!!!

第一章:计算机组成原理

1.1 计算机系统

  • 计算机(Computer),俗称"电脑",是一种能够接收和存储信息,并按照存储在其内部的程序对海量的数据进行自动、高速的处理,然后将处理结果输出的现代化智能电子设备。
  • 计算机有很多形式,如:台式电脑、笔记本电脑、智能手机、平板电脑等,还有生产环境中提供重要业务支撑的各种服务器。

  • 一个完整的计算机系统硬件(Hardware)系统软件(Software)系统两大部分组成,即:

1.2 冯·诺依曼体系结构

  • 冯·诺依曼是一位多才多艺的科学家,他在数学、物理学、计算机科学、经济学等领域都有杰出的贡献。

  • 冯·诺依曼的主要成就:
    • 在计算机科学领域的最著名贡献是提出了冯·诺依曼体系结构(1946 年),这是现代计算机设计的基础
    • 促进了计算机的可编程性和通用性,使得计算机能够执行各种复杂的任务。
    • 对核武器设计、自动化控制系统、人工智能等领域的发展产生了重要影响。
    • ……

IMPORTANT

冯·诺依曼体系结构是现代计算机(量子计算机除外)设计的基础

  • 冯·诺依曼体系结构的理论要点如下:

    • 存储程序程序指令数据都存储在计算机的内存中,这使得程序可以在运行时修改。
    • 二进制逻辑:所有数据指令都以二进制形式表示。
    • 顺序执行:指令按照它们在内存中的顺序执行,但可以有条件地改变执行顺序。
    • 五大部件:计算机由运算器控制器存储器输入设备输出设备组成。
    • 指令结构:指令由操作码和地址码组成,操作码指示要执行的操作,地址码指示操作数的位置。
    • 中心化控制:计算机的控制单元(CPU)负责解释和执行指令,控制数据流。

NOTE

上述的组件协同工作,构成了一个完整的计算机系统:

  • 运算器控制器通常被集成在一起,组成中央处理器(CPU),负责数据处理和指令执行。
  • 存储器(内存)保存数据和程序,是计算机运作的基础。
  • 输入设备输出设备负责与外界的交互,确保用户能够输入信息并接收计算机的处理结果。

1.3 各种硬件处理速度和性能优化

  • 计算机的性能短板:如果 CPU 有每秒处理 1000 个服务请求的能力,各种总线的负载能力能达到 500 个, 但网卡只能接受 200个请求,而硬盘只能负担 150 个的话,那这台服务器得处理能力只能是 150 个请求/ 秒,有 85% 的处理器计算能力浪费了,在计算机系统当中,硬盘的读写速率已经成为影响系统性能进一 步提高的瓶颈。

img

  • 计算机的各个设备部件的延迟从高到低的排列,依次是机械硬盘(HDD)、固态硬盘(SSD)、内存、CPU 。

img

  • 从上图中,我们可以知道,CPU 是最快的,一个时钟周期是 0.3 ns ,内存访问需要 120 ns ,固态硬盘访问需要 50-150 us,传统的硬盘访问需要 1-10 ms,而网络访问是最慢,需要 40 ms 以上。
  • 时间的单位换算如下:
txt
1 秒 = 1000 毫秒,即 1 s = 1000 ms。
+    
Skip to content

IMPORTANT

  • ① C 语言是一门面向过程编译型编程语言,其最大特点在于 运行速度极快,仅次于汇编语言,这使得 C 语言在需要高性能的场景中得到广泛应用,如:操作系统、硬件驱动程序和嵌入式系统。然而,开发效率较低也是 C 语言的一大特点,程序员需要手动管理内存和处理低级别的操作,这对编程能力要求较高。
  • ② C 语言不仅仅是一门编程语言,更是计算机行业的核心语言。它是计算机专业的基础课程,无论是操作系统的构建、硬件驱动的开发,还是数据库系统的实现,都离不开 C 语言的支持。学习 C 语言 不仅是掌握编程技能的必经之路,也是深入理解计算机底层原理的关键。如果忽视了 C 语言的学习,将难以深入理解计算机系统的工作原理,也很难在计算机行业中取得长远的发展。

NOTE

总结就是一句话:C 语言重要(赞),很重要(大赞),非常重要(非常赞),绝对重要(无敌赞),史无前例的重要(一赞到底)!!!

第一章:计算机组成原理

1.1 计算机系统

  • 计算机(Computer),俗称"电脑",是一种能够接收和存储信息,并按照存储在其内部的程序对海量的数据进行自动、高速的处理,然后将处理结果输出的现代化智能电子设备。
  • 计算机有很多形式,如:台式电脑、笔记本电脑、智能手机、平板电脑等,还有生产环境中提供重要业务支撑的各种服务器。

  • 一个完整的计算机系统硬件(Hardware)系统软件(Software)系统两大部分组成,即:

1.2 冯·诺依曼体系结构

  • 冯·诺依曼是一位多才多艺的科学家,他在数学、物理学、计算机科学、经济学等领域都有杰出的贡献。

  • 冯·诺依曼的主要成就:
    • 在计算机科学领域的最著名贡献是提出了冯·诺依曼体系结构(1946 年),这是现代计算机设计的基础
    • 促进了计算机的可编程性和通用性,使得计算机能够执行各种复杂的任务。
    • 对核武器设计、自动化控制系统、人工智能等领域的发展产生了重要影响。
    • ……

IMPORTANT

冯·诺依曼体系结构是现代计算机(量子计算机除外)设计的基础

  • 冯·诺依曼体系结构的理论要点如下:

    • 存储程序程序指令数据都存储在计算机的内存中,这使得程序可以在运行时修改。
    • 二进制逻辑:所有数据指令都以二进制形式表示。
    • 顺序执行:指令按照它们在内存中的顺序执行,但可以有条件地改变执行顺序。
    • 五大部件:计算机由运算器控制器存储器输入设备输出设备组成。
    • 指令结构:指令由操作码和地址码组成,操作码指示要执行的操作,地址码指示操作数的位置。
    • 中心化控制:计算机的控制单元(CPU)负责解释和执行指令,控制数据流。

NOTE

上述的组件协同工作,构成了一个完整的计算机系统:

  • 运算器控制器通常被集成在一起,组成中央处理器(CPU),负责数据处理和指令执行。
  • 存储器(内存)保存数据和程序,是计算机运作的基础。
  • 输入设备输出设备负责与外界的交互,确保用户能够输入信息并接收计算机的处理结果。

1.3 各种硬件处理速度和性能优化

  • 计算机的性能短板:如果 CPU 有每秒处理 1000 个服务请求的能力,各种总线的负载能力能达到 500 个, 但网卡只能接受 200个请求,而硬盘只能负担 150 个的话,那这台服务器得处理能力只能是 150 个请求/ 秒,有 85% 的处理器计算能力浪费了,在计算机系统当中,硬盘的读写速率已经成为影响系统性能进一 步提高的瓶颈。

img

  • 计算机的各个设备部件的延迟从高到低的排列,依次是机械硬盘(HDD)、固态硬盘(SSD)、内存、CPU 。

img

  • 从上图中,我们可以知道,CPU 是最快的,一个时钟周期是 0.3 ns ,内存访问需要 120 ns ,固态硬盘访问需要 50-150 us,传统的硬盘访问需要 1-10 ms,而网络访问是最慢,需要 40 ms 以上。
  • 时间的单位换算如下:
txt
1 秒 = 1000 毫秒,即 1 s = 1000 ms。
 1 毫秒 = 1000 微妙,即 1 ms = 1000 us 。
 1 微妙 = 1000 纳秒,即 1 us = 1000 ns。
  • 按照上图,将计算机世界的时间和人类世界的时间进行对比,即:
txt
如果 CPU 的时钟周期按照 1 秒计算,
 那么,内存访问就需要 6 分钟;
@@ -69,7 +69,7 @@
 }
  • 编程语言就是用于控制计算机,让其完成我们需要的功能。而我们学习编程语言,其实就是学习这些文字和符号编写的规则。
  • 因为 CPU 只能识别二进制的指令,而我们编写的程序叫做源代码,是人类能看懂;但是,计算机却不能识别。那么,我们就需要让计算机能识别我们编写的源程序,就需要将我们编写的源代码交给编译器程序,其会帮助我们将所编写的源代码转换为计算机能够识别的二进制指令。

NOTE

编译器就是运行在操作系统之上的程序,其作用就是用来将程序员编写的源代码转换为计算机能够识别的二进制指令。

  • 如果我们用 Java 语言编写了程序(源代码),那么编写的程序也是不能直接运行的,需要通过 Java 语言的编译器将 Java 程序编译为计算机能够识别的二进制指令。
  • 如果我们用 Python 语言编写了程序(源代码),那么编写的程序也是不能直接运行的,需要通过 Python 语言的编译器将 Python 程序编译为计算机能够识别的二进制指令。
  • ……

NOTE

总结:无论我们学习任何一门编程语言,想要将程序运行起来,都必须做如下的两件事情:

  • ① 学习该语言的文字和符号编写的规则,即:语法规则
  • ② 需要在操作系统上安装对应编程语言的编译器程序,将源程序编译为计算机能够识别的二进制指令。

2.3 计算机语言简史

2.3.1 机器语言(相当于人类的石器时代)

  • 1946 年 2 月 14 日,世界上第一台计算机 ENIAC 诞生,使用的是最原始的穿透卡片

  • 这种卡片使用的是用二进制代码表示的语言,和人类语言差别极大,这种语言就称为机器语言,如:
txt
0000,0000,000000010000 代表 LOAD A, 16
 0000,0001,000000000001 代表 LOAD B, 1
 0001,0001,000000010000 代表 STORE B, 16
  • 这种语言本质上是计算机能识别的唯一语言,人类很难理解;换言之,当时的程序员 99.9% 都是异类!!!

WARNING

  • ① 不同类型(CPU 架构,如:x86_64、arm 等)的处理器有不同的机器语言指令集,指令集架构(ISA)决定了机器语言的具体形式。
  • ② 换言之,机器语言与特定硬件架构紧密相关,机器语言程序几乎没有可移植性。

2.3.2 汇编语言(相当于人类的青铜&铁器时代)

  • 汇编语言使用助记符(如:MOV、ADD、SUB)代替二进制操作码,使程序更易于人类编写和理解;因此,汇编语言也被称为符号语言

  • 汇编语言的优点是能编写高效率的程序;但是,缺点和机器语言没什么不同,汇编语言同样依赖于具体的计算机架构(面向机器),程序不具备跨平台的可移植性。

WARNING

  • ① 汇编语言,目前仍然应用于工业电子编程领域、软件的加密解密、计算机病毒分析等。
  • ② 汇编语言是编程语言的拓荒年代,它非常底层,直接和计算机硬件打交道,开发效率低,学习成本高。

2.3.3 高级语言(相当于人类的信息时代)

  • 高级语言是一种接近于人们使用习惯的程序设计语言。它允许程序员使用接近日常英语的指令来编写程序,程序中的符号和算式也和日常使用的数学公式差不多,接近于自然语言和数学语言,容易被人们掌握。

  • 高级语言独立于计算机硬件,有一定的通用性;计算机不能直接识别和执行用高级语言编写的程序,需要使用编译器解释器转换为机器语言,才能被计算机识别和执行。

NOTE

  • ① 普遍使用的高级编程语言,有:C、C++、Java、Python、C#、JavaScript、Go、SQL 等。
  • ② C 语言是“面向过程”的编程语言,已经脱离了计算机硬件,可以用来设计和开发中等规模的程序。
  • ③ Java、C++、Python、C# 等都是“面向对象”的编程语言(它们在“面向过程”的基础上又增加了很多概念),可以用来设计和开发中大型规模的程序。

IMPORTANT

C 语言出现的时候,已经度过了编程语言的拓荒年代,具备了现代编程语言的特性,但是这个时候还没有出现“软件危机”,人们没有动力去开发更加高级的语言,所以也没有太复杂的编程思想;而之后出现的“面向对象”的编程思想解决了一部分在“软件危机”上的窘境。

2.3.4 总结

  • 编写语言的对比,如下所示:
类别特征优点缺点示例
机器语言直接由计算机执行的二进制代码执行速度快编写困难,可读性差,与具体硬件强绑定二进制代码
汇编语言用助记符代替二进制代码的低级语言相对机器语言更易编写和理解,允许直接控制硬件资源依然需要了解硬件,不够抽象,与具体硬件或平台相关MOV,ADD 等助记符
高级语言接近人类语言,提供了更高层次的抽象易于编写和维护,可移植性好,支持多种编程范式需要通过编译器或解释器转换为机器语言,可能存在一定的性能损失C,Java, Python 等

IMPORTANT

  • ① 使用机器语言进行编程,对于程序员来说,简直就是噩梦,尤其当功能比较多,程序比较大的时候,不但编写麻烦,需要频繁查询指令手册,而且排查错误非常麻烦,要直接面对一堆二进制数据,想想都令人崩溃(上古程序员,可能真的不是“人”,而是“异类”)。此外,使用二进制指令编程,步骤非常繁琐,要考虑各种边界情况和底层问题,开发效率十分低下。
  • ② 这就倒逼程序员开发出了编程语言,提供自己的生产力,如:汇编语言、C 语言、C++ 语言、Java 语言、Go 语言等等,都是在逐步提高开发效率。至此,编程终于不再是只有极客才能做的事情,不怎么了解计算机的初学者在经过一定时间的训练后也可以编写出有模有样的程序。
  • ③ 在实际开发中,随着计算机科学的发展,现代化的高级编程语言,如:C++ 语言、Java 语言、Go 语言等,因其强大的表达能力、良好的可移植性和易用性,成为了日常软件开发的主流选择。

第三章:初识 C 语言

3.1 C 语言究竟是一门怎样的编程语言?

  • 对于绝大多数程序员而言,C 语言是学习编程的第一门语言,很少有不了解 C 语言的程序员。

NOTE

许多著名编程语言的创造者和计算机科学领域的大佬都有学习和使用过 C 语言,如:詹姆斯·高斯林(James Gosling,Java 之父),比雅尼·斯特劳斯特鲁普(Bjarne Stroustrup,C++ 之父),吉多·范罗苏姆(Guido van Rossum,Python 之父),林纳斯·托瓦兹(Linus Torvalds,Linux 之父)等。

  • C 语言除了能让我们了解编程的相关概念,带领我们走进编程的大门,还能让我们明白程序的运行原理,如:

    • ① 计算机的各个部件是如何协同工作的?
    • ② 程序在内存中是一种怎样的状态?
    • ③ 程序在计算机中到底是如何执行的,以及它的生命周期是什么?
    • ④ 操作系统和应用程序之间,又有着怎样的爱恨情仇?
    • ⑤ ...
  • 这些底层知识决定了我们的发展高度,也决定了我们的职业生涯。如果我们希望能在计算机行业中长远的发展,就必须学习这些相关的底层知识。

IMPORTANT

这些底层知识,包括不限于:数据结构和算法、计算机组成原理、操作系统、计算机网络、设计模式以及编译原理(了解即可):

  • 数据结构和算法:主要研究数据的组织方式和处理方法,包括:线性表、树、图等数据结构,以及基本的算法思想和分析方法。

  • 计算机组成原理:主要研究计算机系统的硬件组成和工作原理,包括:数字电路、存储器、中央处理器等内容。

  • 操作系统:主要研究计算机系统的软件组成和工作原理,包括:进程/线程/并发(重点)、内存布局和内存管理(重点)、文件系统和磁盘 IO 等内容,以及基本的操作系统概念和设计思路。

  • 计算机网络:主要研究计算机之间的通信原理和协议,包括:网络体系结构(OSI 模型)、传输协议、网络安全等内容,以及基本的网络概念和技术。重点学习 TCP/IP 协议栈、socket 通信(三/四次握手、select、poll、epoll)、HTTPS/HTTP、长链接等内容。

  • 设计模式:是软件设计中常见问题的通用解决方案。不过,在 C 语言中通常是没有的,因为其是面向过程的编程语言,而 C++ 和 Java 等面向对象的编程语言是有设计模式的。

  • 编译原理:主要研究如何将高级编程语言转换为机器语言,有词法分析、语法分析、语义分析、中间代码生成、优化、代码生成等步骤,了解即可。

  • C 语言的概念少,词汇少,只包含了基本的编程元素,相对比较简单。对于初学者来说,学习 C 语言的时间短,成本小。

NOTE

很多人之所以觉得 C 语言难,就是因为栽倒在 C 语言的指针那边(相对比其他的现代化编程语言而言,C 语言的指针确实足够底层和麻烦,需要掌握的细节很多);但是,一旦有所突破,学习之路就会一马平川。

3.2 C 语言的由来

  • 1969 年,美国贝尔实验室的肯·汤姆森(Ken Thompson)和丹尼斯·里奇(Dennis Ritchie)一起开发了 Unix 操作系统。Unix 最初是使用汇编语言编写的,依赖于计算机硬件。为了程序的可读性可移植性,它们决定使用高级语言重写。但是。当时的高级语言无法满足他们的要求,肯·汤姆森就在 BCPL 语言的基础上发明了 B 语言。
  • 1972 年,丹尼斯·里奇(Dennis Ritchie)在 B 语言的基础上重新设计了一种新的语言,这种新语言取代了 B 语言,即 C 语言。

  • 1973 年,整个 Unix 系统都使用 C 语言重写(重构),大大增强了 Unix 在不同硬件平台的可移植性,这标志着 Unix 的初步成熟,也标志着 C 语言的初步成熟(因为 C 语言可以用于大型项目开发了)。

NOTE

C 语言最初是作为 Unix 系统的开发工具而发明的,它的初衷非常简单,就是被设计成一种非常高效的、可以操作硬件的系统级编程语言,然后帮助团队开发 Unix 操作系统。

  • 此后,这种语言快速流传,广泛用于各种操作系统和系统软件的开发,如:Unix、MS-DOS、Microsoft Windows 以及 Linux 等。

  • 1988 年,美国国家标准协会(ANSI)正式将 C 语言标准化,标志着 C 语言开始稳定和规范化。

3.3 为什么要学习 C 语言?

  • C 语言具有可移植好、跨平台的特点:用 C 语言编写的代码可以在不同的操作系统和硬件平台上编译和运行。

NOTE

  • ① C 语言的最原始的设计目的,就是为了将 Unix 操作系统移植到其他的计算机架构上,这使得它从一开始就非常注重可移植性。
  • ② 这边所说的 C 语言的可移植性,是和汇编语言相比的;如果 C 语言和现代化的高级编程语言相比,可移植性还是很差的,如:Java 的口号是“一次编译,到处运行”,Go 的口号是“一次编译,到处执行”。
  • C 语言在许多领域应用广泛
    • 操作系统:C 广泛用于开发操作系统,如:Unix、Linux 和 Windows。
    • 嵌入式系统:C 是一种用于开发嵌入式系统(如:微控制器、微处理器和其它电子设备)的流程语言。
    • 系统软件:C 用于开发设备驱动程序、编译器和汇编器等系统软件。
    • 网络:C 语言广泛用于开发网络应用程序,例如:Web 服务器、网络协议和网络驱动程序。
    • 数据库系统:C 用于开发数据库系统,例如:Oracle、MySQL 和 PostgreSQL 。
    • 游戏:由于 C 能够处理低级硬件交互,因此经常用于开发计算机游戏。
    • 人工智能:C 用于开发人工智能和机器学习的应用程序,例如:神经网络和深度学习算法。
    • 科学应用:C 用于开发科学应用程序,例如:仿真软件和数值分析工具。
    • 金融应用:C 用于开发股票市场分析和交易系统等金融应用。
  • ③ C 语言能够直接对硬件进行操作、管理内存以及和操作系统对话,这使得它是一种非常接近底层的语言,非常适合写需要和硬件交互、有极高性能要求的程序。

NOTE

  • C 语言毕竟诞生的时间非常早(20 世纪 70 年代),属于 70 后了,有点落后于现在的时代,虽然执行效率高(仅次于汇编语言),但是开发效率低。
  • 随着时间的推移,人们在 C 语言的基础上增加了面向对象的机制(软件危机),形成了一门新的编程语言,它的名字是 C++ 。
  • 但是,C++ 的特性实在是太多了(因为 C++ 兼容 C,并增加了很多自己独有的特性,可以是当今最复杂的编程语言,没有之一),于是人们在 C++ 的基础上,删减了一些非必要的特性,就形成了 Java 和 C# ,也可以认为 Java 和 C# 是 C++--。
  • 当然,近年来,Go 语言也很火,它的设计者之一就是 Unix 操作系统的的开发者肯·汤姆森(Ken Thompson),Go 诞生的背景据说是肯·汤姆森(Ken Thompson)在 C++ 委员会在为其演讲 C++ 新特性的时候,觉得 C++ 新特性太多太复杂,于是就开发了 Go 语言;所以,Go 语言中有很多 C 语言的身影。
  • 其实,在 C 语言之后的许多编程语言,或多或少都参考了 C 语言;所以,编程界流传了一句话:汇编生 C ,C 生万物。
  • 学习 C 语言有助于快速上手其他编程语言,如:C++(原先是 C 语言的一个扩展,在 C 语言的基础上嫁接了面向对象编程思想)、C#、Java 等,这些语言都继承或深受 C 语言的影响和启发。
  • ⑤ C 语言长盛不衰。C 语言至今,依然是最广泛使用、最流行的编程语言之一,包括很多大学将 C 语言作为计算机教学的入门语言,拥有庞大而活跃的用户社区,这意味着有许多资源和库可供开发人员使用。
  • ⑥ C 语言容易学习,适合入门。和 Java、C++、Python 等更加现代化的高级编程语言相比,C 语言涉及的概念少,附带的标准库小,整体比较简单,容易学习,非常适合初学者入门。

3.4 计算机语言排行榜

  • TIOBE 是一个流行编程语言排行,每月更新。排名权重基于世界范围内工程师数量,Google、Bing、Yahoo! 、Wikipedia、Amazon、Youtube 和百度这些主流的搜索引擎,也将作为排名权重的参考指标。

  • 计算机语言走势图:

3.5 C 语言到底能做什么?

3.5.1 概述

  • 我们知道,这个世界上的编程语言太多太多。其中,最流行的编程语言就是 TOBIE 榜单上的前 50 名。

  • 从应用的范围上来讲,编程语言大致可以分为以下两类,如下所示:

    • 通用型编程语言:这些语言设计的目的是能够用于开发多种类型的应用程序,不局限于某个特定领域。它们通常拥有丰富的库和框架支持,可以应用于系统编程、应用开发、Web开发、数据分析等多个领域。
    • 专用型编程语言:这些语言是为了解决特定领域的问题而设计的,通常在该领域中表现出色。虽然它们可以在一定程度上用于其他领域,但其核心设计和优化是针对某个特定应用场景的。
  • 常见的专用型编程语言,如下所示:

专用型编程语言描述
SQL专门用于数据库查询和管理,尽管可以嵌入其他编程语言中,但其主要应用是数据库操作。
R主要用于统计分析和数据可视化,广泛应用于数据科学和研究领域。
MATLAB主要用于数值计算、算法开发和数据可视化,广泛应用于工程和科学领域。
VHDL/Verilog用于硬件描述和数字电路设计,主要应用于电子工程领域。
  • 常见的通用型编程语言,如下所示:
通用型编程语言描述
Python广泛应用于Web开发、数据科学、自动化脚本、人工智能等。
Java用于企业级应用、移动应用开发(Android)、Web 开发等。
C++可用于系统编程、游戏开发、嵌入式系统等多个领域。
JavaScript最初用于 Web 前端开发,现在也广泛用于服务器端(Node.js)、桌面应用开发(Electron)等。

NOTE

C 语言是一门通行型的编程语言,并没有针对某个领域进行优化。但是,C 语言也有很多常见的应用领域。

3.5.2 C 语言的常见应用领域

  • C 语言的常见应用领域,如下所示:
    • ① 单片机或嵌入式开发:单片机通常是一个集成度较高的微控制器,资源有限,如:家电控制、自动化设备、传感器数据采集、智能玩具、汽车电子。嵌入式系统是一个计算机系统,嵌入在更大设备中,用来执行专门的任务。它通常包含硬件和软件两部分,具有专用性、实时性、资源受限等特点,如:消费电子(如智能手机、智能手表)、医疗设备、工业控制系统、汽车电子系统(ECU、ABS)、物联网设备等。
    • 上位机开发(桌面软件开发):其实,这部分的市场已经被其它编程语言蚕食了,如:C++ 的 QT、GTK,Java 的 Swing 、JavaFx,Dart 的 Flutter ,因为 C 语言太过于底层,本身不直接支持跨平台,而且没有丰富的库和框架支持。
    • ③ 系统组件开发:
      • 基础组件,如:文件系统等。
      • 核心算法,如:加密/安全算法(MD5、SHA、AES、RSA、SSL)等。
      • 硬件驱动,如:声卡驱动、显卡驱动、网卡驱动等。
      • 通信协议,如:TCP/IP协议族(UDP、DNS、路由选择)、HTTP/HTTPS 等。
    • ④ 开发操作系统:这是 C 语言的初衷,它就是为开发操作系统而生的。
    • ⑤ 开发其它编程语言:
      • 有些编程语言的编译器(解释器)和标准库就使用 C 语言开发,如: Python、PHP、Rust、Perl。
      • 有些编程语言是在 C 语言的基础上进行的扩展,如: C++、Objective-C、Swift。
    • ⑥ 信号处理:C 语言在电气工程领域也有很多用途,它可以使用信号处理算法来管理微处理器、微控制器等集成电路。
    • ⑦ 音视频处理:C 语言的速度非常快,能够快速地对音频和视频数据进行处理。音频和视频数据通常比较大,需要高效的算法和数据结构来处理,而C语言运行速度非常快,能够及时处理这些数据。C 语言提供了丰富的底层库和工具,如:FFmpeg、OpenCV 等,这些库和工具可以方便地对音频和视频数据进行编码、解码、剪辑、处理和转换等操作。
    • ⑧ 数据库开发:数据库是软件领域的基础设施,它的性能直接影响整个应用程序的运行效率,所以必须使用一种高效的语言进行开发。使用 C 语言开发的数据库有:MySQL、SQLite、PostgreSQL 等。
    • ⑨ ...

IMPORTANT

虽然 C 语言的开发场景貌似看起来很多;但是,使用 C 语言的场景几乎就是:底层/系统开发 + 关键组件/模块的开发 + 贴近硬件的开发,这些开发场景非常关注运行效率,或者响应时间,或者硬件资源。

3.6 不学 C 语言,行吗?

  • C 语言相比于其它的现代化高级编程语言而言,如:Java、Go 等,实在是太老了;如果不打算搞嵌入式开发,即便学了,一时半会也用不上。但是,几乎所有大学的计算机/软件专业都将 C 语言作为必修课,这又是为什么呢?
  • 其实,是因为 C 语言是一门基础语言,很多其它的课程都依赖 C 语言。如果你不了解 C 语言,很多课程你是理解不了的,如下所示:
    • ① 编译原理课程通常是以 C 语言为例进行讲解,因为 C 语言的编译过程相对简单、规范和透明,适合教学。
    • ② 数据结构课程通常也是使用 C 语言进行编程,因为 C 语言比较底层,能够让大家看到数据结构的各种细节。另外,数据结构是一种被频繁调用的组件,必须要追求效率,C 语言再合适不过了。
    • ③ 学习操作系统原理(内存、进程、线程、通信等)也要具备 C 语言基础,否则是学不明白的。
    • ...
  • C 语言是一门面向计算机的语言,它能帮助我们快速了解底层;而其它的高级语言(Python、Java、C# 等)是面向用户的,它能让我们快速上手,搞出点实用的工具来,比如:桌面软件、网站、APP 等。

NOTE

  • ① 借助 C 语言学习原理,相当于修炼内功;使用其它语言开发程序,相当于精通招式。
  • ② 一个既有扎实“内功”又精通“招式”的程序员,无疑能够更好地应对各种编程挑战。
  • 从整体上讲,计算机软件大概可以分为两种:
    • 一种是基础设施,如:操作系统、数据库、浏览器、云计算系统、大数据系统、编译器/编程语言、通信协议、区块链、标准库/运行库、算法实现等。
    • 一种是应用软件,如:桌面软件、APP、网站、小程序等。

IMPORTANT

  • ① 内功不扎实的话,开发一般的应用软件可能没什么问题。但是,如果想要开发高性能的软件,或者开发基础设施,那是绝对是不行的。
  • ② 万丈高楼平地起,勿在浮沙筑高台!!!

3.7 C 语言的版本选择

3.7.1 概述

  • C 语言是在 B 语言的基础上改进而来的,目的是为了更好地开发 Unix 操作系统。到了 1973 年,Unix 的大部分功能都被 C 语言重写,这标志着 C 语言的初步成熟,因为它可以用于大型项目了。
  • 后来,C 语言被多次改进,越来越强大,为了规范 C 语言的特性和功能,人们发布了多个 C 语言标准。

3.7.2 版本 1(K&R C)

  • K&R C 指的是 C 语言的原始版本。1978 年,C 语言的发明者布莱恩·柯林(Brian Kernighan)和丹尼斯·里奇(Dennis Ritchie)合写了一本著名的教材《C 编程语言》(The C programming language)。

NOTE

由于 C 语言还没有成文的语法标准,这本书就成了公认标准,以两位作者的姓氏首字母作为版本简称 “K&R C”。

3.7.3 版本 2(ANSI C,又称 C89 或 C90)

  • 到了 80 年代,C 语言越来越流行,广泛被业界使用,从大型主机到小型微机,各个厂商群雄并起,推出了多款 C 语言的编译器。这些编译器根据行业和厂商自己的需求,进行了各种扩展,C 语言进入了春秋战国时代,逐渐演变成一个松散杂乱的大家族。
  • 为统一 C 语言版本,1989 年,美国国家标准协会(ANSI)制定了一套 C 语言标准,并于次年被国际标准化组织(ISO)通过。它被称为 “ANSI C”,也可以按照发布年份,称为 “C89 或 C90”。

NOTE

目前常用的编译器,如:MSVC(Microsoft Visual C++)、GCC、LLVM Clang 等,都能很好地支持 ANSI C 的内容。

3.7.4 版本 3(C99)

  • C 语言标准的第一次大型修订,发生在 1999 年,增加了许多语言特性,如:双斜杠( // )的注释语法,可变长度数组、灵活的数组成员、复数、内联函数和指定的初始值设定项,这个版本称为 C99,是目前最流行的 C 版本

NOTE

这个时候的 C 语言编译器基本已经成熟,各个组织对 C99 的支持所表现出来的兴趣不同:

  • 当 GCC 和其它一些商业编译器支持 C99 的大部分特性的时候。
  • 微软和 Borland 却似乎对此不感兴趣,或者说没有足够的资源和动力来改进编译器。

最终导致不同的编译器在部分语法上存在差异。典型的例子就是:ANSI C 规定,只能用常量表示数组的长度,而 C99 取消了这个限制,数组的长度也可以用变量表示(可变长度数组)。对于 C99 的这个新改动,GCC 和 Clang 是支持的,而 MSVC 却不支持。

3.7.5 版本 4(C11)

  • 2011 年,标准化组织再一次对 C 语言进行修订,增加了_Generic、static_assert 和原子类型限定符,这个版本称为 C11。

NOTE

  • ① 需要强调的是,修订标准的原因并不是因为原标准不能用,而是需要跟进新的技术。
  • ② 支持此标准的主流 C 语言编译器有 GCC、LLVM Clang、Intel C++ Compile 等。

3.7.6 版本 5(C17)

  • C11 标准在 2017 年进行了修补,但发布是在 2018 年。新版本只是解决了 C11 的一些缺陷,没有引入任何新功能,这个版本称为 C17。

3.7.7 版本 6(C23)

  • 2023 年发布,计划进一步增强安全性,消除实现定义的行为,引入模块化语言概念等新特性,使 C 语言在安全和可靠性方面有重大提高。

第四章:C 语言的学习技巧

4.1 如何学习 C 语言?

  • 对于大部分的初学者, 学习 C 语言的目的可能是为了成为一名合格的程序员,开发出优秀的软件。但是,在学习了 C 语言的基本语法后,却发现只能在控制台黑底白字)上玩玩,没有漂亮的用户界面以及人性化的交互。于是,开始学习数据结构、算法、数据库、操作系统,越陷越深,越来越迷茫,不知道学习 C 语言能做什么,认为学习编程很难,开始怀疑自己,直到放弃!!!
  • 其实,C 语言本身就是一门非常简单的语言,提供的实用功能不多,大部分的时候需要借助操作系统、第三方库以及以及一些硬件,如:单片机等,才能发挥它的威力!!!

IMPORTANT

  • ① 学习 C 语言仅仅是让你踏上程序员之路的第一步而已,只学习 C 语言也做不了什么。
  • ② 系统、扎实的学习 C 语言可以让你了解底层硬件、一些简单的数据结构和算法,并培养计算机思维。
  • 前文,我们提过:C 语言是一门通用性的语言,并没有针对某个领域进行优化。并且,在实际项目中,C 语言主要用于比较底层的开发,例如:
    • Windows、Linux、Unix 等操作系统的内核 90% 以上都使用 C 语言开发(Rust 语言有望未来,在操作系统开发中占据一席之地,特别是在对安全性和性能要求极高的领域)。
    • 开发硬件驱动,让硬件和操作系统连接起来,这样用户才能更有效的使用硬件。
    • 单片机和嵌入式属于软硬件的结合,是使用 C 语言最多的地方。
    • 开发系统组件或服务,用于支撑上层应用。
    • 如果对软件某个模块,例如:算法和搜索部分的效率要求较高,也可以使用 C 语言来开发。
    • ……
  • 貌似感觉 C 语言的应用还是很多的啊,那为什么感觉学习 C 语言还是做不了什么?原因除了 C 语言通常都是开发最底层的应用之外,最重要的一点就是生态

IMPORTANT

现代化的高级编程语言的流行程度,除了和编程语言的设计是否优秀有关,最主要的原因就是生态

  • ① 很多编程语言都自带标准库(语言本身提供的,开箱即用),如:Java、Go 等。
  • ② 很多编程语言都有自己的包管理器(用于管理第三方库)解决方案,如:Java 中的 Maven、Gradle、Go 中的 go modules ,JavaScript 的 npm 等。

遗憾的是,C 语言的标准库非常简单,只有输入输出文件操作日期时间字符串处理内存管理,对于网络编程GUI数据库并发需要大量的第三方库操作系统的功能来扩展 C 语言的功能(Java 语言、Go 语言等其他的现代化高级编程语言,都是直接将这些常见的开发场景内置到标准库中,开箱即用,极大的降低了软件开发的难度)。C 语言的第三方库也不是很多(和其它现代化高级编程语言相比),社区也不是很活跃(和其它现代化高级编程语言相比),更别提缺少自己的包管理器。

不过,现在 C 语言社区也开始诞生了一些包管理器,如:Conan 和 vcpkg ;也有自己的项目构建工具,如:cmake 、xmake 等。

NOTE

JavaScript 的作者 Brendan Eich(布兰登·艾奇) 曾经这么说:“与其说我爱 JavaScript,不如说我恨它。它是 C 语言和 Self 语言一夜情的产物(致敬 C 语言)。十八世纪英国文学家约翰逊博士说得好:"它的优秀之处并非原创,它的原创之处并不优秀。"”

4.2 项目构建工具和包管理器

4.2.1 概述

  • 项目构建工具包管理器在软件开发中扮演着不同的角色,它们虽然有时会有重叠的功能,但主要关注的点是不同的。

4.2.2 项目构建工具

  • 项目构建工具是用于自动化编译、测试、打包、部署等一系列任务的软件工具。它们帮助开发者简化和管理整个软件开发生命周期中的各个步骤,尤其是在构建过程中的复杂性管理上。
  • 其功能有:
    • 编译代码:自动编译源代码(如 :.java.c 等)为可执行文件或中间文件(如:.class 文件)。
    • 运行测试:集成单元测试、集成测试,自动运行测试用例并生成报告。
    • 打包:将编译后的代码、依赖库、资源文件等打包成可分发的格式(如:JAR、WAR、可执行文件等)。
    • 依赖管理:自动下载、更新和管理项目所需的第三方库(这部分功能有时与包管理器重叠)。
    • 部署:将打包后的应用程序自动部署到测试环境、生产环境等。
    • 任务自动化:除了基本的构建流程外,还可以自动化执行一些常见任务,如:代码检查、文档生成等。
  • 常用的项目构建工具:
    • Maven(Java):一个流行的构建工具和依赖管理工具,广泛用于 Java 项目。
    • Gradle(Java、Kotlin、Groovy):一个灵活的构建工具,支持声明式的构建脚本和多种语言。
    • Make(C/C++):一个经典的构建工具,使用 Makefile 来定义构建规则和依赖关系。
    • CMake(C/C++):一个跨平台的构建系统,帮助生成标准的构建文件,如:Makefile 或 Visual Studio 项目文件。
    • ……

4.2.3 包管理器

  • 包管理器是用于自动化安装、更新、配置管理软件包及其依赖关系的工具。它主要关注于获取和管理项目所需的第三方库或工具包,并确保它们正确地集成到项目中。
  • 其功能有:
    • 依赖管理:根据项目配置文件(如:package.jsonrequirements.txt)自动下载和安装项目所需的依赖包。
    • 版本控制:管理包的版本,允许开发者指定某个特定版本或版本范围,确保项目中的库版本一致性。
    • 包的发布和共享:开发者可以通过包管理器发布自己的库,并且共享给社区或组织内部的其他项目使用。
    • 环境隔离:有些包管理器提供虚拟环境功能,可以将不同项目的依赖隔离开,避免版本冲突。
    • 更新和卸载:包管理器可以自动更新依赖包到最新的兼容版本或卸载不再需要的包。
  • 常见的包管理器:
    • npm(Node.js):用于管理 JavaScript 和 Node.js 项目的包和模块。
    • pip(Python):用于安装和管理 Python 的软件包。
    • Cargo(Rust):Rust 编程语言的包管理器和构建工具。
    • Yarn(JavaScript):是 npm 的替代品,提供更快和更可靠的包管理体验。
    • Homebrew(macOS):用于 macOS 系统下的命令行工具和库的管理。
    • ……

4.2.3 注意事项

  • 对于 Java 项目中的 MavenGradle 而言,其不仅是项目构建工具也是包管理工具

NOTE

  • ① Gradle 也支持原生项目的开发,如:C 和 C++ 。
  • ② 不过,目前而言,业界开发 C/C++ 项目时,使用最多的项目构建工具和包管理器是 Cmake 和 Conan 。

第五章:附录

5.1 嵌入式领域中的 C 语言

5.1.1 概述

  • C 语言在 C51、STM32 和 ARM 平台上的应用场景非常广泛,涵盖了各种嵌入式系统的开发需求。

5.1.2 C51(8051 系列微控制器)

  • 背景:8051 是由 Intel 于 1980 年设计的一种 8 位微控制器架构。它具有指令集简单、结构紧凑的特点,广泛应用于低端嵌入式系统中。
  • 开发工具:C51 是指针对 8051 系列微控制器的 C 语言编译器,如:Keil C51。这种编译器将 C 语言代码编译为适合 8051 架构的汇编代码。
  • C 语言的作用:C 语言在 8051 微控制器上的应用使得开发更加高效和可维护。尽管 8051 的硬件资源有限,但 C 语言仍然能够在不损失性能的前提下提供高级编程的便利。
  • 应用场景
    • 简单的控制系统:家用电器(微波炉、洗衣机、空调)的控制板等。这些设备通常不需要复杂的运算能力,但要求可靠和稳定的控制。
    • 低功耗传感器接口:C51 微控制器常用于低功耗传感器的数据采集和传输,如:温度、湿度、压力传感器。
    • 工业自动化设备:用于简单的工业自动化控制,如:小型电机驱动、工业传感器数据处理和传输。
    • 电子玩具:许多简单的电子玩具使用 8051 系列微控制器来控制声音、LED 灯光、显示屏等。

NOTE

总结:C51 微控制器适用于资源受限、需要低成本的简单控制系统,非常适合使用 C 语言来进行开发!!!

5.1.3 STM32(STM32 系列微控制器)

  • 背景:STM32 是意法半导体(STMicroelectronics)推出的一系列基于 ARM Cortex-M 内核的 32 位微控制器。它们广泛用于需要高性能和低功耗的嵌入式应用中,如:工业控制、消费电子和物联网设备。
  • 开发工具:开发 STM32 微控制器通常使用 Keil、IAR Embedded Workbench 或 STM32CubeIDE 等开发环境。这些环境中使用的编程语言主要是 C(有时也包括 C++)。
  • C 语言的作用:C 语言在 STM32 上的应用非常广泛,开发者可以利用它直接控制硬件寄存器,同时也能方便地使用 STM32 提供的 HAL(硬件抽象层)库或 LL(低层)库进行开发。C 语言在这个平台上不仅能实现底层控制,还能编写复杂的应用逻辑。
  • 应用场景
    • 物联网(IoT)设备:STM32 微控制器常用于各种物联网设备,如:智能家居控制系统、环境监测设备、可穿戴设备等。这些设备通常需要低功耗和强大的处理能力,并且需要支持多种通信协议,如:Wi-Fi、Bluetooth、LoRa。
    • 消费电子:智能手表、健身追踪器、电子书阅读器、无人机等,这些设备需要具备实时处理能力、低功耗和良好的外设支持。
    • 医疗设备:STM32 微控制器被广泛应用于便携式医疗设备中,如:血糖监测仪、心率监测器、便携式超声设备等,这些设备需要精确的传感器数据采集和处理。
    • 工业自动化控制:PLC(可编程逻辑控制器)、工业机器人、伺服电机控制等,STM32 能够处理复杂的控制算法和实时任务。
    • 汽车电子:用于汽车中的传感器管理、车载信息娱乐系统、车身控制系统(车窗、电动座椅调节等)。

NOTE

总结:STM32 微控制器在物联网、消费电子、医疗设备和工业控制等领域表现出色,非常适合使用 C 语言来进行开发,因为 C 语言允许直接进行硬件控制并支持复杂的应用开发。

5.1.3 ARM 架构(特别是 ARM Cortex 系列)

  • 背景:ARM 是一种广泛使用的处理器架构,特别是在嵌入式系统中,ARM Cortex 系列处理器(如 Cortex-M、Cortex-R 和 Cortex-A)非常流行。Cortex-M 系列主要用于微控制器,Cortex-R 用于实时系统,Cortex-A 则用于高性能嵌入式系统。
  • 开发工具:针对 ARM 架构的开发,常用工具包括 ARM Keil MDK、IAR、GCC for ARM 和 ARM Development Studio。这些工具均支持使用 C 语言进行开发。
  • C 语言的作用:C 语言在 ARM 架构上的应用广泛。它被用于操作系统内核(如 FreeRTOS、Zephyr)、设备驱动、应用层逻辑等。在 ARM Cortex-M 和 Cortex-R 系列中,C 语言的高效性和低级别硬件访问能力是开发实时、低延迟系统的关键。
  • 应用场景
    • 高级嵌入式操作系统:ARM Cortex-A 系列处理器广泛用于运行 Linux、Android 等操作系统的嵌入式设备,如:智能手机、平板电脑、智能电视和车载娱乐系统。
    • 实时系统:ARM Cortex-R 系列处理器用于实时系统,如:汽车的 ABS(防抱死制动系统)、ESC(电子稳定控制系统),以及航空电子设备,这些系统要求极低的延迟和高可靠性。
    • 高性能物联网网关:Cortex-A 系列处理器可以用来开发支持多协议、多设备管理的物联网网关,这些网关通常需要强大的计算能力和多线程处理能力。
    • 边缘计算设备:在边缘计算场景中,ARM Cortex-A 处理器用于执行本地数据处理和决策,如:视频分析、图像处理、语音识别等。
    • 智能家居设备:ARM Cortex-M 系列微控制器广泛应用于智能家居产品,如:智能灯泡、智能音箱、家庭安全系统,这些设备需要高效的处理能力和低功耗。
    • 机器人控制系统:ARM Cortex-M 和 Cortex-A 系列处理器用于机器人系统的控制和通信,如:无人机、工业机器人、服务机器人等,处理复杂的运动控制、路径规划和传感器数据融合。

NOTE

总结:ARM Cortex 系列适用于从实时系统到高级嵌入式操作系统的各类应用,支持从低功耗控制到高性能计算的多种需求,非常适合使用 C 语言来进行开发,因为 C 语言不仅用于控制硬件,还广泛应用于操作系统和应用程序的开发。

5.2 C 和 C++ 的关系

  • 起源和发展:
    • C 语言:C 语言由丹尼斯·里奇(Dennis Ritchie)在 1972 年开发,最初用于开发操作系统,特别是 UNIX。它是一种结构化的编程语言,提供了对硬件的低级访问,且效率高,因此在系统编程中广泛使用。
    • C++ 语言:C++ 由比雅尼·斯特劳斯特鲁普(Bjarne Stroustrup)在 20 世纪 80 年代初开发,作为 C 语言的扩展。它引入了面向对象编程的概念,同时保留了 C 语言的高效性和底层操作能力。C++ 最初被称为 “C with Classes”(带类的 C),后来发展成一种独立的编程语言。
  • 兼容型:
    • 语法兼容:C++ 几乎完全兼容 C 语言的语法,这意味着大多数 C 代码可以在 C++ 编译器下直接编译运行。C++ 可以看作是 C 语言的超集(虽然不完全是 100% 兼容,但差异较少)。
    • 扩展性:C++ 在 C 的基础上增加了许多新特性,如:类和对象、继承、多态、模板和异常处理等。这使得 C++ 不仅适合系统编程,还可以用于开发复杂的应用程序。
  • 编程范式:
    • C 语言:主要是面向过程编程,强调的是函数调用和控制结构。
    • C++ 语言:支持多种编程范式,包括:面向过程、面向对象和泛型编程,使得开发者可以更灵活地选择适合的编程风格。
  • 性能与应用:
    • 性能:由于 C++ 包含了更多的高级特性,它的编译时间和运行时开销可能比 C 稍高。但得益于其优化机制,C++ 仍然可以实现与 C 语言相近的性能。
    • 应用场景:C 语言仍然在嵌入式系统、驱动程序开发和其他对性能要求极高的场合中占据重要地位。而 C++ 则被广泛用于游戏开发、图形处理、大型软件系统等需要复杂结构和抽象的领域。

NOTE

C++ 是 C 语言的继承者和扩展,它保留了 C 语言的优势,并引入了更多现代编程语言的特性,使得它在更广泛的应用领域中得到应用。

Released under the MIT License.

- + \ No newline at end of file diff --git a/notes/01_c-basic/01_xdx/index.html b/notes/01_c-basic/01_xdx/index.html index 0539051..90267cf 100644 --- a/notes/01_c-basic/01_xdx/index.html +++ b/notes/01_c-basic/01_xdx/index.html @@ -22,7 +22,7 @@ -
Skip to content

第一章:开发环境的安装和配置(⭐)

1.1 什么是编译器?

  • 要开发 C/C++ 程序,需要安装 C/C++ 编译器,目前有两种主流实现,即:
    • GCC(GNU Compiler Collection):全平台实现,即支持 Windows、MacOS、Linux 等。
    • MSVC(Microsoft Visual C++):只支持 Windows 系统。
  • GCC 在 Windows 上的版本有很多,如:MinGW-w64GygwinMSYS2。它们之间的区别,如下所示:
特性MinGW-w64CygwinMSYS2
简介Minimalist GNU for WindowsPOSIX 兼容环境和工具集结合了 MinGW 和 Cygwin 的工具集
编译器提供 GCC 编译器提供 POSIX 兼容环境,包含大量工具提供 MinGW-w64 工具链和 Cygwin 环境
生成文件Windows 原生可执行文件POSIX 兼容的可执行文件可以生成 Windows 原生可执行文件或 POSIX 文件
依赖无需额外依赖依赖 Cygwin DLL根据使用工具链决定(MinGW-w64 无依赖,Cygwin 有依赖)
工具和库基本的编译工具丰富的 Unix 工具和库丰富的工具和库,强大的包管理系统
性能性能较好可能较低,因为通过兼容层调用系统取决于使用的工具链(MinGW-w64 性能较好)
复杂度简单易用设置和使用相对复杂较为灵活,复杂度介于 MinGW-w64 和 Cygwin 之间
适用场景开发 Windows 原生应用运行和开发 Unix 程序混合使用 Unix 工具和开发 Windows 原生应用
优点轻量级,直接生成 Windows 应用完整的 POSIX 兼容环境,丰富的工具灵活的环境,强大的包管理系统
缺点工具和库较少生成文件依赖 Cygwin DLL,性能可能较低环境较大,占用更多空间,复杂性比 MinGW-w64 高

NOTE

  • ① MinGW-w64 、Cygwin 以及 MSYS2 任选其一安装即可。
  • ② 目前的 Win10 和 Win11 版本支持 WSL2 (Windows Sub Linux 2 ,即 Windows 的子系统 Linux),可以实现在 Windows 系统上安装一个 Linux ,然后再运行 Linux 中的 GCC 工具链。
  • ③ 本人的操作系统是 Win11 ,安装和配置都将以该系统为基础作为演示,后续不再赘述!!!

1.2 编译器的安装和配置

1.2.2 MinGW-w64 的安装和配置

1.2.2.1 安装

  • 下载到本地:略。

NOTE

下载地址在这里

  • 解压到指定的目录,即:

NOTE

本人的解压目录是:D:\develop\mingw64

1.2.2.2 配置 path 环境变量

  • 配置环境变量,以便任意目录都可以执行 gcc 命令,即:

NOTE

因为,本人安装 MinGW-w64 的目录是 D:\develop\mingw64,所以本人需要配置的 path 环境变量就是D:\develop\mingw64\bin

  • 测试是否安装成功:
shell
gcc --version

1.2.3 Cygwin 的安装和配置

1.2.3.1 安装

  • 下载到本地:略。

NOTE

下载地址在这里

  • 点击安装:

NOTE

默认是最小化安装,没有 GCC,需要选择 gcc-core、gcc-g++、make、gdb、binutils 。

1.2.3.2 配置 path 环境变量

  • 1.2.2.2 配置 path 环境变量 步骤相同:略。

1.2.4 MSYS2(推荐)

1.2.4.1 安装

  • 下载到本地:略。

NOTE

下载地址在这里

  • 点击安装:

NOTE

可能很多人,会遇到安装到 50% 就一直卡死在那边,不用慌,关闭它,再次重新安装即可。

  • 出现命令终端:

NOTE

如果没有出现命令终端,也不要慌,去 Win11 操作系统的开始菜单,那边找一下,就能找到。

  • 替换清华镜像源(可选):
shell
sed -i \
+    
Skip to content

第一章:开发环境的安装和配置(⭐)

1.1 什么是编译器?

  • 要开发 C/C++ 程序,需要安装 C/C++ 编译器,目前有两种主流实现,即:
    • GCC(GNU Compiler Collection):全平台实现,即支持 Windows、MacOS、Linux 等。
    • MSVC(Microsoft Visual C++):只支持 Windows 系统。
  • GCC 在 Windows 上的版本有很多,如:MinGW-w64GygwinMSYS2。它们之间的区别,如下所示:
特性MinGW-w64CygwinMSYS2
简介Minimalist GNU for WindowsPOSIX 兼容环境和工具集结合了 MinGW 和 Cygwin 的工具集
编译器提供 GCC 编译器提供 POSIX 兼容环境,包含大量工具提供 MinGW-w64 工具链和 Cygwin 环境
生成文件Windows 原生可执行文件POSIX 兼容的可执行文件可以生成 Windows 原生可执行文件或 POSIX 文件
依赖无需额外依赖依赖 Cygwin DLL根据使用工具链决定(MinGW-w64 无依赖,Cygwin 有依赖)
工具和库基本的编译工具丰富的 Unix 工具和库丰富的工具和库,强大的包管理系统
性能性能较好可能较低,因为通过兼容层调用系统取决于使用的工具链(MinGW-w64 性能较好)
复杂度简单易用设置和使用相对复杂较为灵活,复杂度介于 MinGW-w64 和 Cygwin 之间
适用场景开发 Windows 原生应用运行和开发 Unix 程序混合使用 Unix 工具和开发 Windows 原生应用
优点轻量级,直接生成 Windows 应用完整的 POSIX 兼容环境,丰富的工具灵活的环境,强大的包管理系统
缺点工具和库较少生成文件依赖 Cygwin DLL,性能可能较低环境较大,占用更多空间,复杂性比 MinGW-w64 高

NOTE

  • ① MinGW-w64 、Cygwin 以及 MSYS2 任选其一安装即可。
  • ② 目前的 Win10 和 Win11 版本支持 WSL2 (Windows Sub Linux 2 ,即 Windows 的子系统 Linux),可以实现在 Windows 系统上安装一个 Linux ,然后再运行 Linux 中的 GCC 工具链。
  • ③ 本人的操作系统是 Win11 ,安装和配置都将以该系统为基础作为演示,后续不再赘述!!!

1.2 编译器的安装和配置

1.2.2 MinGW-w64 的安装和配置

1.2.2.1 安装

  • 下载到本地:略。

NOTE

下载地址在这里

  • 解压到指定的目录,即:

NOTE

本人的解压目录是:D:\develop\mingw64

1.2.2.2 配置 path 环境变量

  • 配置环境变量,以便任意目录都可以执行 gcc 命令,即:

NOTE

因为,本人安装 MinGW-w64 的目录是 D:\develop\mingw64,所以本人需要配置的 path 环境变量就是D:\develop\mingw64\bin

  • 测试是否安装成功:
shell
gcc --version

1.2.3 Cygwin 的安装和配置

1.2.3.1 安装

  • 下载到本地:略。

NOTE

下载地址在这里

  • 点击安装:

NOTE

默认是最小化安装,没有 GCC,需要选择 gcc-core、gcc-g++、make、gdb、binutils 。

1.2.3.2 配置 path 环境变量

  • 1.2.2.2 配置 path 环境变量 步骤相同:略。

1.2.4 MSYS2(推荐)

1.2.4.1 安装

  • 下载到本地:略。

NOTE

下载地址在这里

  • 点击安装:

NOTE

可能很多人,会遇到安装到 50% 就一直卡死在那边,不用慌,关闭它,再次重新安装即可。

  • 出现命令终端:

NOTE

如果没有出现命令终端,也不要慌,去 Win11 操作系统的开始菜单,那边找一下,就能找到。

  • 替换清华镜像源(可选):
shell
sed -i \
     "s#https\?://mirror.msys2.org/#https://mirrors.tuna.tsinghua.edu.cn/msys2/#g" \
     /etc/pacman.d/mirrorlist*

  • 安装 gcc 等相关开发包:
shell
pacman -Syu --noconfirm # 更新包管理器
shell
pacman -Sy base-devel --noconfirm # 安装开发工具包
shell
pacman -Sy mingw-w64-ucrt-x86_64-toolchain --noconfirm # 安装开发 gcc 相关工具链

NOTE

也许,你会看到其他人的安装命令是 pacman -Sy mingw-w64-x86_64-toolchain --noconfirm,此处解释下两者的区别:

  • mingw-w64-x86_64-toolchain 使用更传统的 MSVCRT,适合需要经典 MinGW 环境的项目或依赖较老 C 运行时的应用。
  • mingw-w64-ucrt-x86_64-toolchain 使用 Microsoft 的 UCRT,更适合现代 Windows 开发,提供更好的兼容性和性能。

1.2.4.2 配置 path 环境变量

  • 1.2.2.2 配置 path 环境变量 步骤相同:略。

NOTE

本人需要配置的 path 环境变量是 C:\msys64\ucrt64\bin

1.3 什么是 IDE(集成开发环境)?

  • 在实际开发中,除了编译器是必须安装的工具之外,我们往往还需要很多其他的辅助软件,如下所示:

    • 编辑器:用来编写代码,并且给代码着色,以方便阅读。
    • 代码提示器:输入部分代码,即可提示全部代码,加速代码的编写过程。
    • 调试器:观察程序的每一个运行步骤,发现程序的逻辑错误。
    • 项目管理工具:对程序涉及到的所有资源进行管理,包括:源文件、图片、视频、第三方库等。
    • 漂亮的界面:各种按钮、面板、菜单、窗口等控件整齐排布,操作更方便。
  • 这些工具通常被打包在一起,统一安装和发布,如:Visual Studio、CLion 以及 VS Code ,通常统称为集成开发环境(IDE,Integrated Development Environment)。

NOTE

  • ① IDE(集成开发环境)就是一系列开发工具的组合套装。这就好比台式机,核心部件是主机。主机就相当于 IDE 的代码编辑器和编译器,有了它们,开发者就可以进行基本的编程工作。然而,正如我们在购买台式机时,通常还会附带显示器、键盘、鼠标、U盘、摄像头等外围设备,IDE 也同样提供了一系列额外的工具和插件,比如:调试器、版本控制集成、代码补全、代码重构工具等。这些“外围设备”让开发过程更加高效、直观,并且能够满足更多的开发需求,使得 IDE 成为一个完整的开发环境。
  • ② 严格来讲, VS Code 属于编辑器,而不是 IDE;但是,可以通过安装各种插件,来完成 IDE 的功能;而 Visual Studio 和 CLion 属于 IDE。
  • ③ 在实际开发中,使用 IDE 进行编程并不是一种非常丢人的事情。而使用编辑器,如:记事本vi/vim 等,进行编程,也并不是一件非常骄傲的事情。可能有些人会在网上发布这样的言论:“学习编程,刚开始需要使用记事本vi/vim等简单的编辑器软件,不要使用 IDE ”,目的可能是为了让初学者熟悉编程的基础概念和语法,并避免依赖 IDE 的辅助功能。但是,这种方法或许可以起到锻炼基础技能的功能,但这并不意味着 IDE 就不适合初学者。事实上,许多 IDE 还提供了初学者友好的界面和工具,可以帮助新手更快地入门和理解编程。

1.43 IDE 的安装和配置

1.4.1 CLion

1.4.1.1 概述

  • CLion 是一款由 JetBrains 推出的跨平台 C/C++ 集成开发环境(IDE),它具有智能编辑器、CMake 构建支持、调试器、单元测试、代码分析等功能,可以极大提高 C/C++ 开发效率。

NOTE

  • ① 本次,演示的 CLion 的安装版本是 2024.1.4 ,后续版本可能会更新,但是操作几乎不会发生太多变化!!!
  • ② CLion 作为一个 IDE,本身就携带了各个平台(操作系统)的 C 语言编译器,如:Windows 中就是 MinGW;但是,CLion 中自带的 C 语言编译器版本可能并非我们实际开发所想要的,这也是在 Windows 中,为什么推荐使用 MSYS2 的原因所在。

1.4.1.2 安装

  • 鼠标双击,进入安装:

  • 下一步:

  • 下一步:

  • 下一步:

  • 安装:

  • 安装完成:

1.4.1.3 配置

  • 打开 CLion :

  • 安装中文插件(可选):

NOTE

对于以中文、韩语和日语为母语的开发者,CLion 在 2024.2 之后的版本就绑定了本地化插件,即不需要再安装本地化插件了。

  • 配置新 UI :

  • 新 UI 配置自定义字体(可选):

  • 配置自动保存功能:

  • 配置文件编码 为 UTF-8:

  • 配置控制台编码为 UTF-8:

  • 配置显示方法分隔符功能:

  • 配置编辑器的字体(可选):

  • 检测 GCC 工具链是否安装成功:

1.4.2 VS Code

1.4.2.1 概述

  • Visual Studio Code (VS Code) 是一个免费的开源代码编辑器,适用于 Windows、MacOS 和 Linux 平台。它支持语法高亮、智能代码补全(IntelliSense)、内置调试工具和Git集成。用户可以通过扩展来添加更多功能,如:支持新的编程语言、主题和调试工具。VS Code 还支持在微软 Azure 上进行部署和托管,适用于各种编程语言和框架。

NOTE

  • ① Visual Studio Code 需要安装对应的插件,才能运行 C/C++ 代码。
  • ② Visual Studio Code 除了开源免费的优点之外,还有一个优点就是插件巨多(几乎所有主流的编程语言都提供有对应的插件),这也是很多程序员喜欢使用它的原因。

1.4.2.2 安装

  • 鼠标双击,进入安装:

  • 同意协议:

  • 下一步:

  • 下一步:

  • 下一步:

  • 安装:

  • 安装过程:

  • 安装完成:

1.4.2.3 配置

  • 安装中文插件:

  • 安装 C/C++ 插件:

1.4.3 Microsoft Visual Studio

1.4.3.1 概述

  • Visual Studio(简称 VS)是由微软公司发布的集成开发环境。它包括了整个软件生命周期中所需要的大部分工具,如:UML 工具、代码管控工具、项目版本控制 Git 等。
  • Visual Studio 支持 C/C++、C#、F#、VB 等多种程序语言的开发和测试,可以用于生成 Web 应用程序,也可以生成桌面应用程序,功能十分强大,但下载和安装很可能耗时数小时,还可能会塞满磁盘。
  • Visual Studio 有三种版本:社区版(免费,不支持企业使用),专业版(收费)和企业版(收费)。企业版拥有面向架构师的功能、高级调试和测试,这些功能是另外两种版本所没有的。
  • Visual Studio 旨在成为世界上最好的 IDE(集成开发环境),号称“宇宙第一强大 IDE”。

NOTE

本次,演示的 Visual Studio 的安装版本是 Visual Studio 2022 ,后续版本可能会更新,但是操作几乎不会发生太多变化!!!

1.4.3.2 安装

  • 鼠标双击,进入安装:

  • 继续:

  • 等待:

  • 工作负荷(使用 C++ 的桌面开发):

  • 单个组件:

  • 语言包:

  • 安装位置(修改默认的安装位置):

  • 如果不是第一次安装,可能会出现共享组件、工具和 SDK不可以修改,即:

  • 此时,就需要打开注册表编辑器,将如下图中的除了第一个选项,全部删除,然后关闭再重新安装,即:

  • 开始安装:

  • 安装中:

  • 安装完成,然后关闭:

1.4.3.3 配置

  • 在开始菜单处,启动 VS :

  • 登录或跳过该选项(有微软账号就注册,没有就暂时跳过):

  • 继续:

  • 注册 VS :

  • 填写注册码:

NOTE

  • ① Pro 版本:TD244-P4NB7-YQ6XK-Y8MMM-YWV2J
  • ② Enterprise 版本:VHF9H-NXBBB-638P6-6JHCY-88JWH

第二章:C 语言入门(HelloWorld,⭐)

2.1 手动版

  • ① 新建一个 HelloWorld.c 的文件:

  • ② 通过记事本等软件打开该文件,输入如下的代码,并保存:
c
#include <stdio.h>
 
@@ -307,7 +307,7 @@
     --depth 1 \
     --single-branch --branch=linux-msft-wsl-${KERNEL_VERSION} \
     https://github.com/microsoft/WSL2-Linux-Kernel.git

  • 编译内核代码:
shell
cd WSL2-Linux-Kernel
shell
make -j $(nproc) KCONFIG_CONFIG=Microsoft/config-wsl

  • 编译 perf 工具:
shell
cd tools/perf
shell
make clean && make

  • 复制到 PATH 变量所指向的路径中:
shell
cp perf /usr/bin/

8.4.3 整合

  • CLion 中配置 perf 的路径:

  • 在 CLion 中通过 perf 运行代码:

8.5 Win 中文乱码问题

  • 前文,我们提及到,在 Win 中,如果出现中文乱码问题,就需要去语言和区别设置系统区域的编码为 UTF-8 ;但是,这样可能会造成其它的软件出现中文乱码问题,如:Xshell 等。

NOTE

  • ① 之所以,修改系统的编码为 UTF-8 会出现问题,是因为早期的 Win 系统的中文默认编码是 GBK(目前也是,Win 并没有强制第三方软件使用 UTF-8 编码) ,而 Xshell 等也使用的这些编码,一旦我们修改为 UTF-8 之后,可能会造成这些第三方软件出现中文乱码问题(第三方软件适配问题,相信将来应该都会切换为 UTF-8 编码),体验较差!!!
  • ② 在 Linux 或 MacOS 之所以不会出现中文乱码的问题,是因为这些系统默认的编码就是 UTF-8 。
  • 其实,还有一种解决方案,如下所示:

  • 测试一下,是否配置成功:

8.6 CLion 中自动导入头文件

  • 在 CLion 中,最为强大的功能就是直接输入函数,然后让 IDE 帮我们自动导入头文件,包括自定义的头文件,相当实用。

NOTE

  • ① CLion 中的自动导入头文件快捷键Alt + Enter
  • ② CLion 中的自动提取变量的类型快捷键Ctrl + Alt + V

  • 开启自动导入头文件的步骤,如下所示:

Released under the MIT License.

- + \ No newline at end of file diff --git a/notes/01_c-basic/02_xdx/index.html b/notes/01_c-basic/02_xdx/index.html index 977c837..5ab7dda 100644 --- a/notes/01_c-basic/02_xdx/index.html +++ b/notes/01_c-basic/02_xdx/index.html @@ -22,7 +22,7 @@ -
Skip to content

第一章:变量(⭐)

1.1 程序中变化的数据

  • 在生活中,我们使用最多的不是固定的数据,而是会变化的数据:
    • ① 购物车商品的数量价格等。
    • ② 一首歌播放的时间进度条歌词的展示等。
    • ③ 微信聊天中消息条数时间语音的长度头像名称等。
    • ④ 游戏中技能的冷却时间血量蓝量buff 时间金币的数量等。
    • ……
  • 下图是一个购物车变化数据,即:

  • 那么,在实际开发中,我们就会使用变量保存操作这些变化数据

1.2 变量

  • 变量的定义:变量是程序中不可或缺的组成单位,最基本的存储单元。其实,变量就是一个存储数据的临时空间,可以向其中存储不同类型的数据,如:整数、小数、字符、字符串等,并且变量中的数据在程序运行的时候可以动态改变。

NOTE

  • 变量:用来存储数据容器
  • 数据:可以是一个用来计算的数字,如:上文购物车中的价格等;也可以是一句话中的关键词其它任意格式的数据
  • 变量的特别之处就在于它存放的数据是可以改变的。
  • 我们可以将变量想象为一个容器,盒子中装的就是我们想要的数据,并且我们需要盒子一个特别的名称;通过这个特别的名称,我们可以盒子添加数据移除数据,这个特别的名称就是变量名

NOTE

  • 变量是内存中的一个存储区域,该区域的数据可以在同一类型范围内不断变化
  • ② 通过变量名,可以操作这块内存区域,向其中存储数据获取数据以及移除数据
  • ③ 变量的构成包含三个要素:数据类型变量名需要存储的数据
  • ④ 在生活中,我们会经常说:这件衣服的价格是 100(整型) 元,这双鞋子的价格是 250.5(小数,浮点类型) 元,今天天气真好(字符串类型)之类的话;在计算机科学中,这些都是数据,并且它们是有类型,即:数据类型。(数据类型用于定义变量所能存储的数据的种类以及可以对这些数据进行的操作的一种分类,每种数据类型都有特定的属性和用途,它们决定了变量在内存中如何表示和存储,以及变量可以执行哪些操作)

1.3 变量的声明和使用

  • ① 变量必须先声明,后使用。
  • ② 可以先声明变量再赋值,也可以在声明变量的同时进行赋值。
  • ③ 变量的值可以在同一类型范围内不断变化。

IMPORTANT

  • ① 在实际开发中,我们通常都会在声明变量的同时,给其赋值,这被称为初始化。
  • ② 如果不在声明变量的同时,进行初始化,默认情况下,系统会赋予的随机值,我们也称为垃圾值。
  • 示例:先声明,再使用
c
#include <stdio.h>
+    
Skip to content

第一章:变量(⭐)

1.1 程序中变化的数据

  • 在生活中,我们使用最多的不是固定的数据,而是会变化的数据:
    • ① 购物车商品的数量价格等。
    • ② 一首歌播放的时间进度条歌词的展示等。
    • ③ 微信聊天中消息条数时间语音的长度头像名称等。
    • ④ 游戏中技能的冷却时间血量蓝量buff 时间金币的数量等。
    • ……
  • 下图是一个购物车变化数据,即:

  • 那么,在实际开发中,我们就会使用变量保存操作这些变化数据

1.2 变量

  • 变量的定义:变量是程序中不可或缺的组成单位,最基本的存储单元。其实,变量就是一个存储数据的临时空间,可以向其中存储不同类型的数据,如:整数、小数、字符、字符串等,并且变量中的数据在程序运行的时候可以动态改变。

NOTE

  • 变量:用来存储数据容器
  • 数据:可以是一个用来计算的数字,如:上文购物车中的价格等;也可以是一句话中的关键词其它任意格式的数据
  • 变量的特别之处就在于它存放的数据是可以改变的。
  • 我们可以将变量想象为一个容器,盒子中装的就是我们想要的数据,并且我们需要盒子一个特别的名称;通过这个特别的名称,我们可以盒子添加数据移除数据,这个特别的名称就是变量名

NOTE

  • 变量是内存中的一个存储区域,该区域的数据可以在同一类型范围内不断变化
  • ② 通过变量名,可以操作这块内存区域,向其中存储数据获取数据以及移除数据
  • ③ 变量的构成包含三个要素:数据类型变量名需要存储的数据
  • ④ 在生活中,我们会经常说:这件衣服的价格是 100(整型) 元,这双鞋子的价格是 250.5(小数,浮点类型) 元,今天天气真好(字符串类型)之类的话;在计算机科学中,这些都是数据,并且它们是有类型,即:数据类型。(数据类型用于定义变量所能存储的数据的种类以及可以对这些数据进行的操作的一种分类,每种数据类型都有特定的属性和用途,它们决定了变量在内存中如何表示和存储,以及变量可以执行哪些操作)

1.3 变量的声明和使用

  • ① 变量必须先声明,后使用。
  • ② 可以先声明变量再赋值,也可以在声明变量的同时进行赋值。
  • ③ 变量的值可以在同一类型范围内不断变化。

IMPORTANT

  • ① 在实际开发中,我们通常都会在声明变量的同时,给其赋值,这被称为初始化。
  • ② 如果不在声明变量的同时,进行初始化,默认情况下,系统会赋予的随机值,我们也称为垃圾值。
  • 示例:先声明,再使用
c
#include <stdio.h>
 
 int main() {
 
@@ -262,7 +262,7 @@
 
     return 0;
 }

3.3 进制的运算规则

  • 十进制的运算规则,如下所示:
    • (针对加法而言)。
    • (针对减法而言)。
  • 二进制的运算规则,如下所示:
    • (针对加法而言)。
    • (针对减法而言)。
  • 八进制的运算规则,如下所示:
    • (针对加法而言)。
    • (针对减法而言)。
  • 十六进制的运算规则,如下所示:
    • 十六(针对加法而言)。
    • 十六(针对减法而言)。

3.4 进制的转换

3.4.1 概述

  • 不同进制的转换,如下所示:

  • 在计算机中,数据是从右往左的方式排列的;其中,最右边的是低位,最左边的是高位,即:

3.4.2 二进制和十进制的转换

3.4.2.1 二进制转换为十进制

  • 规则:从最低位开始,将每个位上的数提取出来,乘以 2 的 (位数 - 1 )次方,然后求和。

NOTE

  • ① 在学术界,将这种计算规则,称为位权相加法
  • 八进制转换为十进制十六进制转换为十进制二进制转换为十进制的算法相同!!!
  • 示例:十进制转十进制

  • 示例:二进制转十进制

3.4.2.2 十进制转换二进制

  • 规则:将该数不断除以 2 ,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的二进制。

NOTE

  • ① 在学术界,将这种计算规则,称为短除法连续除2取余法
  • ② 很好理解,只有不断地除以 2 ,就能保证最大的数字不超过 2 ,这不就是二进制(只能有 0 或 1)吗?
  • 八进制转换为二进制十六进制转换为二进制十进制转换为二进制的算法相同!!!
  • 示例:十进制转十进制

  • 示例:十进制转二进制

3.4.3 二进制转八进制

  • 规则:每 3 位二进制就是一个八进制。

  • 示例:011 101 001 -> 351

3.4.4 二进制转十六进制

  • 规则:每 4 位二进制就是一个十六进制。

  • 示例:1110 1001 -> 0xE9

3.5 原码、反码和补码

3.5.1 概述

  • 机器数:一个数在计算机的存储形式是二进制,我们称这些二进制数为机器数。机器数可以是有符号的,用机器数的最高位来存放符号位,0 表示正数,1 表示负数。

  • 真值:因为机器数带有符号位,所以机器数的形式值不等于其真实表示的值(真值),以机器数 1000 0001 为例,其真正表示的值(首位是符号位)为 -1,而形式值却是 129 ,因此将带有符号位的机器数的真正表示的值称为机器数的真值。

3.5.2 原码

  • 原码的表示与机器数真值表示的一样,即用第一位表示符号,其余位表示数值。
  • 规则:
    • 正数的原码是它本身对应的二进制数,符号位是 0 。
    • 负数的原码是它本身绝对值对应的二进制数,但是符号位是 1 。
  • +1 的原码,使用 8 位二进数来表示,就是:
十进制数原码(8位二进制数)
+10000 0001
  • -1 的原码,使用 8 位二进数来表示,就是:
十进制数原码(8位二进制数)
-11000 0001

IMPORTANT

按照原码的规则,会出现 +0-0 的情况,即:0000 0000(+0)、1000 0000(-0),显然不符合实际情况;所以,计算机底层虽然存储和计算的都是二进数,但显然不是原码。

3.5.3 反码

  • 规则:

    • 正数的反码和它的原码相同。
    • 负数的反码是在其原码的基础上,符号位不变,其余各位取反。
  • +1 的反码,使用 8 位二进数来表示,就是:

十进制数原码(8位二进制数)反码(8位二进制数)
+10000 00010000 0001
  • -1 的反码,使用 8 位二进数来表示,就是:
十进制数原码(8位二进制数)反码(8位二进制数)
-11000 00011111 1110

IMPORTANT

按照反码的规则,如果是 +0,对应的原码是 0000 0000;那么,其反码还是 0000 0000 ;如果是 -0,对应的原码是 1000 0000,其反码是 1111 1111,显然不符合实际情况;所以,计算机底层虽然存储和计算的都是二进数,但显然不是反码。

3.5.4 补码

  • 规则:

    • 正数的补码和它的原码相同。
    • 负数的补码是在其反码的基础上 + 1 。
  • +1 的补码,使用 8 位二进数来表示,就是:

十进制数原码(8位二进制数)反码(8位二进制数)补码(8位二进制数)
+10000 00010000 00010000 0001
  • -1 的补码,使用 8 位二进数来表示,就是:
十进制数原码(8位二进制数)反码(8位二进制数)补码(8位二进制数)
-11000 00011111 11101111 1111
  • 如果 0 ,按照 +0 的情况进行处理,即:

  • 如果 0 ,按照 -0 的情况进行处理,即:

IMPORTANT

  • ① 补码表示法解决了原码反码存在的两种零(+0-0)的问题,即:在补码表示法中,只有一个零,即 0000 0000。
  • ②补码使得加法运算减法运算可以统一处理,通过将减法运算转换为加法运算,可以简化硬件设计,提高了运算效率。
  • ③ 计算机底层存储计算的都是二进数的补码

3.5.5 总结

  • ① 正数的原码、反码和补码都是一样的,三码合一。
  • ② 负数的反码是在其原码的基础上,按位取反(0 变 1 ,1 变 0 ),符号位不变;负数的补码是其反码 + 1 。
  • ③ 0 的补码是 0 。

3.6 计算机底层为什么使用补码?

  • 如果计算是 2 - 2 ,那么可以转换为 2 + (-2),这样计算机内部在处理减法计算的时候,就会将其转换为加法计算的形式,以简化硬件设计和提高计算效率。
  • 最高位表示符号位,由于符号位的存在,如果使用原码来计算,就会导致计算结果不正确,即:

  • 补码的设计可以巧妙的让符号位也参与计算,并且可以得到正确的计算结果,即:

Released under the MIT License.

- + \ No newline at end of file diff --git a/notes/01_c-basic/03_xdx/index.html b/notes/01_c-basic/03_xdx/index.html index 1244136..897499c 100644 --- a/notes/01_c-basic/03_xdx/index.html +++ b/notes/01_c-basic/03_xdx/index.html @@ -22,7 +22,7 @@ -
Skip to content

第一章:数据类型(⭐)

1.1 概述

  • 根据变量存储不同,我们可以将变量分为两类:

    • 普通变量:变量所对应的内存中存储的是普通值
    • 指针变量:变量所对应的内存中存储的是另一个变量的地址
  • 如下图所示:

NOTE

普通变量和指针变量的相同点:

  • 普通变量有内存空间,指针变量也有内存空间。
  • 普通变量有内存地址,指针变量也有内存地址。
  • 普通变量所对应的内存空间中有值,指针变量所对应的内存空间中也有值。

普通变量和指针变量的不同点:

  • 普通变量所对应的内存空间存储的是普通的值,如:整数、小数、字符等;指针变量所对应的内存空间存储的是另外一个变量的地址。
  • 普通变量有普通变量的运算方式,而指针变量有指针变量的运算方式(后续讲解)。
  • 那么,在 C 语言中变量的数据类型就可以这么划分,如下所示:

NOTE

  • 根据普通变量存储的类型不同,可以将普通变量类型划分为基本数据类型(整型、字符类型、浮点类型、布尔类型)和复合数据类型(数组类型、结构体类型、共用体类型、枚举类型)。
  • 根据指针变量指向空间存储的类型不同,可以将指针类型分为基本数据类型指针复合数据类型指针函数指针数组指针等,例如:如果指针所指向的空间保存的是 int 类型,那么该指针就是 int 类型的指针。

1.2 整数类型

1.2.1 概述

  • 整数类型简称整型,用于存储整数值,如:12、20、50 等。
  • 根据所占内存空间大小的不同,可以将整数类型划分为:
  • ① 短整型:
类型存储空间(内存空间)取值范围
unsigned short (无符号短整型)2 字节0 ~ 65,535 (2^16 - 1)
[signed] short(有符号短整型,默认)2 字节-32,768 (- 2^15) ~ 32,767 (2^15 -1)
  • ② 整型:
类型存储空间(内存空间)取值范围
unsigned int(无符号整型)4 字节(通常)0 ~ 4294967295 (0 ~2^32 -1)
[signed] int(有符号整型,默认)4 字节(通常)-2147483648(- 2^31) ~ 2147483647 (2^31-1)
  • ③ 长整型:
类型存储空间(内存空间)取值范围
unsigned long(无符号长整型)4 字节(通常)0 ~2^32 -1
[signed] long(有符号长整型,默认)4 字节(通常)- 2^31 ~ 2^31-1
  • ④ 长长整型:
类型存储空间(内存空间)取值范围
unsigned long long(无符号长整型)8 字节(通常)0 ~2^64 -1
[signed] long long(有符号长整型,默认)8 字节(通常)- 2^63 ~ 2^63-1

NOTE

  • ① C 语言默认没有规定各种数据类型所占存储单元的长度,但是通常需要遵守:sizeof(short int) ≤ sizeof(int) ≤ sizeof(long int) ≤ sizeof(long long) ,具体的存储空间由编译系统自行决定;其中,sizeof 是测量类型或变量、常量长度的运算符。
  • ② short 至少 2 个字节,long 至少 4 个字节。
  • ③ 之所以这么规定,是为了可以让 C 语言长久使用,因为目前主流的 CPU 都是 64 位,但是在 C语言刚刚出现的时候,CPU 还是以 8 位和 16 位为主。如果当时就将整型定死为 8 位或 16 位,那么现在我们肯定不会再学习 C 语言了。
  • ④ 整型分为有符号 signed 和无符号 unsigned 两种,默认是 signed。
  • ⑤ 在实际开发中,最常用的整数类型就是 int 类型了,如果取值范围不够,就使用 long 或 long long 。
  • ⑥ C 语言中的格式占位符非常多,只需要大致了解即可;因为,我们在实际开发中,一般都会使用 C++ 或 Rust 以及其它的高级编程语言,如:Java 等,早已经解决了需要通过格式占位符来输入和输出变量。

1.2.2 短整型(了解)

  • 语法:
c
unsigned short x = 10 ; // 无符号短整型
c
short x = -10; // 有符号短整型

NOTE

  • ① 有符号表示的是正数、负数和 0 ,即有正负号。无符号表示的是 0 和正数,即正整数,没有符号。
  • ② 在 printf无符号短整型(unsigned short)格式占位符%hu有符号短整型(signed short)格式占位符%hd
  • ③ 可以通过 sizeof 运算符获取无符号短整型(unsigned short)有符号短整型(signed short)存储空间(所占内存空间)
  • ③ 可以通过 #include <limits.h> 来获取 无符号短整型(unsigned short)有符号短整型(signed short)取值范围
  • 示例:定义和打印短整型变量
c
#include <stdio.h>
+    
Skip to content

第一章:数据类型(⭐)

1.1 概述

  • 根据变量存储不同,我们可以将变量分为两类:

    • 普通变量:变量所对应的内存中存储的是普通值
    • 指针变量:变量所对应的内存中存储的是另一个变量的地址
  • 如下图所示:

NOTE

普通变量和指针变量的相同点:

  • 普通变量有内存空间,指针变量也有内存空间。
  • 普通变量有内存地址,指针变量也有内存地址。
  • 普通变量所对应的内存空间中有值,指针变量所对应的内存空间中也有值。

普通变量和指针变量的不同点:

  • 普通变量所对应的内存空间存储的是普通的值,如:整数、小数、字符等;指针变量所对应的内存空间存储的是另外一个变量的地址。
  • 普通变量有普通变量的运算方式,而指针变量有指针变量的运算方式(后续讲解)。
  • 那么,在 C 语言中变量的数据类型就可以这么划分,如下所示:

NOTE

  • 根据普通变量存储的类型不同,可以将普通变量类型划分为基本数据类型(整型、字符类型、浮点类型、布尔类型)和复合数据类型(数组类型、结构体类型、共用体类型、枚举类型)。
  • 根据指针变量指向空间存储的类型不同,可以将指针类型分为基本数据类型指针复合数据类型指针函数指针数组指针等,例如:如果指针所指向的空间保存的是 int 类型,那么该指针就是 int 类型的指针。

1.2 整数类型

1.2.1 概述

  • 整数类型简称整型,用于存储整数值,如:12、20、50 等。
  • 根据所占内存空间大小的不同,可以将整数类型划分为:
  • ① 短整型:
类型存储空间(内存空间)取值范围
unsigned short (无符号短整型)2 字节0 ~ 65,535 (2^16 - 1)
[signed] short(有符号短整型,默认)2 字节-32,768 (- 2^15) ~ 32,767 (2^15 -1)
  • ② 整型:
类型存储空间(内存空间)取值范围
unsigned int(无符号整型)4 字节(通常)0 ~ 4294967295 (0 ~2^32 -1)
[signed] int(有符号整型,默认)4 字节(通常)-2147483648(- 2^31) ~ 2147483647 (2^31-1)
  • ③ 长整型:
类型存储空间(内存空间)取值范围
unsigned long(无符号长整型)4 字节(通常)0 ~2^32 -1
[signed] long(有符号长整型,默认)4 字节(通常)- 2^31 ~ 2^31-1
  • ④ 长长整型:
类型存储空间(内存空间)取值范围
unsigned long long(无符号长整型)8 字节(通常)0 ~2^64 -1
[signed] long long(有符号长整型,默认)8 字节(通常)- 2^63 ~ 2^63-1

NOTE

  • ① C 语言默认没有规定各种数据类型所占存储单元的长度,但是通常需要遵守:sizeof(short int) ≤ sizeof(int) ≤ sizeof(long int) ≤ sizeof(long long) ,具体的存储空间由编译系统自行决定;其中,sizeof 是测量类型或变量、常量长度的运算符。
  • ② short 至少 2 个字节,long 至少 4 个字节。
  • ③ 之所以这么规定,是为了可以让 C 语言长久使用,因为目前主流的 CPU 都是 64 位,但是在 C语言刚刚出现的时候,CPU 还是以 8 位和 16 位为主。如果当时就将整型定死为 8 位或 16 位,那么现在我们肯定不会再学习 C 语言了。
  • ④ 整型分为有符号 signed 和无符号 unsigned 两种,默认是 signed。
  • ⑤ 在实际开发中,最常用的整数类型就是 int 类型了,如果取值范围不够,就使用 long 或 long long 。
  • ⑥ C 语言中的格式占位符非常多,只需要大致了解即可;因为,我们在实际开发中,一般都会使用 C++ 或 Rust 以及其它的高级编程语言,如:Java 等,早已经解决了需要通过格式占位符来输入和输出变量。

1.2.2 短整型(了解)

  • 语法:
c
unsigned short x = 10 ; // 无符号短整型
c
short x = -10; // 有符号短整型

NOTE

  • ① 有符号表示的是正数、负数和 0 ,即有正负号。无符号表示的是 0 和正数,即正整数,没有符号。
  • ② 在 printf无符号短整型(unsigned short)格式占位符%hu有符号短整型(signed short)格式占位符%hd
  • ③ 可以通过 sizeof 运算符获取无符号短整型(unsigned short)有符号短整型(signed short)存储空间(所占内存空间)
  • ③ 可以通过 #include <limits.h> 来获取 无符号短整型(unsigned short)有符号短整型(signed short)取值范围
  • 示例:定义和打印短整型变量
c
#include <stdio.h>
 
 int main() {
 
@@ -791,7 +791,7 @@
 
     return 0;
 }

2.8 运算符优先级

  • C 语言中运算符的优先级,如下所示:
优先级运算符名称或含义结合方向
1[]数组下标➡️(从左到右)
()圆括号
.成员选择(对象)
->成员选择(指针)
2-负号运算符⬅️(从右到左)
(类型)强制类型转换
++自增运算符
--自减运算符
*取值运算符
&取地址运算符
!逻辑非运算符
~按位取反运算符
sizeof长度运算符
3/➡️(从左到右)
*
%余数(取模)
4+➡️(从左到右)
-
5<<左移➡️(从左到右)
>>右移
6>大于➡️(从左到右)
>=大于等于
<小于
<=小于等于
7==等于➡️(从左到右)
!=不等于
8&按位与➡️(从左到右)
9^按位异或➡️(从左到右)
10|按位或➡️(从左到右)
11&&逻辑与➡️(从左到右)
12||逻辑或➡️(从左到右)
13?:条件运算符⬅️(从右到左)
14=赋值运算符⬅️(从右到左)
/=除后赋值
*=乘后赋值
%=取模后赋值
+=加后赋值
-=减后赋值
<<=左移后赋值
>>=右移后赋值
&=按位与后赋值
^=按位异或后赋值
|=按位或后赋值
15,逗号运算符➡️(从左到右)

WARNING

  • ① 不要过多的依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用小括号来控制表达式的执行顺序。
  • ② 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它分成几步来完成。
  • ③ 运算符优先级不用刻意地去记忆,总体上:一元运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 三元运算符 > 赋值运算符。

第三章:附录

3.1 字符集和字符集编码

3.3.1 概述

  • 字符集和字符集编码(简称编码)计算机系统中处理文本数据的两个基本概念,它们密切相关但又有区别。
  • 字符集(Character Set)是一组字符的集合,其中每个字符都被分配了一个唯一的编号(通常是数字)。字符可以是字母、数字、符号、控制代码(如换行符)等。字符集定义了可以表示的字符的范围,但它并不直接定义如何将这些字符存储在计算机中。

NOTE

ASCII(美国信息交换标准代码)是最早期和最简单的字符集之一,它只包括了英文字母、数字和一些特殊字符,共 128 个字符。每个字符都分配给了一个从 0 到 127 的数字。

  • 字符集编码(Character Encoding,简称编码)是一种方案或方法,它定义了如何将字符集中的字符转换为计算机存储和传输的数据(通常是一串二进制数字)。简而言之,编码是字符到二进制数据之间的映射规则。

NOTE

ASCII 编码方案定义了如何将 ASCII 字符集中的每个字符表示为 7 位的二进制数字。例如:大写字母'A'在 ASCII 编码中表示为二进制的1000001,十进制的 65

  • 字符集字符集编码之间的关系如下:

  • Linux 中安装帮助手册:

3.3.2 ASCII 编码

  • 冯·诺依曼体系结构中,我们知道,计算机中所有的数据指令都是以二进制的形式表示的;所以,计算机中对于文本数据的数据也是以二进制来存储的,那么对应的流程如下:

  • 我们知道,计算机是上个世纪 60 年代在美国研制成功的,为了实现字符和二进制的转换,美国就制定了一套字符编码,即英语字符和二进制位之间的关系,即 ASCII (American Standard Code for Information Interchange)编码:
    • ASCII 编码只包括了英文字符、数字和一些特殊字符,一共 128 个字符,并且每个字符都分配了唯一的数字,范围是 0 - 127。
    • ASCII 编码中的每个字符都使用 7 位的二进制数字表示;但是,计算机中的存储的最小单位是 1 B = 8 位,那么最高位统一规定为 0 。

NOTE

  • ① 其实,早期是没有字符集的概念的,只是后来为了解决乱码问题,而产生了字符集的概念。
  • ② 对于英文体系来说,a-zA-Z0-9以及一些特殊字符一共 128 就可以满足实际存储需求;所以,在也是为什么 ASCII 码使用 7 位二进制(2^7 = 128 )来存储的。
  • 在操作系统中,就内置了对应的编码表,Linux 也不例外;可以使用如下的命令查看:
shell
man ascii

  • 其对应的 ASCII 编码表,如下所示:

  • 但是,随着计算机的发展,计算机开始了东征之路,由美国传播到东方:

  • 先是传播到了欧洲,欧洲在兼容 ASCII 编码的基础上,推出了 ISO8859-1 编码,即:
    • ISO8859-1 编码包括基本的拉丁字母表、数字、标点符号,以及西欧语言中特有的一些字符,如:法语中的 è、德语中的 ü 等。
    • ISO 8859-1 为每个字符分配一个单字节(8 位)编码,意味着它可以表示最多 256 (2^8)个不同的字符(编号从 0 到 255)。
    • ISO 8859-1 的前 128 个字符与 ASCII 编码完全一致,这使得 ASCII 编码的文本可以无缝转换为 ISO 8859-1 编码。

  • 计算机继续传播到了亚洲,亚洲(双字节)各个国家分别给出了自己国家对应的字符集编码,如:
    • 日本推出了 Shift-JIS 编码:
      • 单字节 ASCII 范围:0 - 127。
      • 双字节范围:
        • 第一个字节:129 - 159 和 224 - 239 。
        • 第二个字节:64 - 126 和 128 - 252 。
    • 韩国推出了 EUC-KR 编码:
      • 单字节 ASCII 范围:0 - 127。
      • 双字节范围:从 41281 - 65278。
    • 中国推出了 GBK 编码:
      • 单字节 ASCII 范围:0 - 127。
      • 双字节范围:33088 - 65278 。

NOTE

  • ① 通过上面日本、韩国、中国的编码十进制范围,我们可以看到,虽然这些编码系统在技术上的编码范围存在重叠(特别是在高位字节区域),但因为它们各自支持的字符集完全不同,所以实际上它们并不直接冲突。
  • ② 但是,如果一个中国人通过 GBK 编码写的文章,通过邮件发送给韩国人,因为韩国和中国在字符集编码上的高位字节有重叠部分,必然会造成歧义。

3.3.3 Unicode 编码

  • 在 Unicode 之前,世界上存在着数百种不同的编码系统,每一种编码系统都是为了支持特定语言或一组语言的字符集。这些编码系统,包括:ASCII、ISO 8859 系列、GBK、Shift-JIS、EUC-KR 等,它们各自有不同的字符范围和编码方式。这种多样性虽然在局部范围内解决了字符表示的问题,但也带来了以下几个方面的挑战:

    • 编码冲突:由于不同的编码系统可以为相同的字节值分配不同的字符,因此在不同编码之间转换文本时,如果没有正确处理编码信息,就很容易产生乱码。这种编码冲突在尝试处理多种语言的文本时尤为突出。
    • 编码的复杂性:随着全球化的发展,软件和系统需要支持越来越多的语言,这就要求开发者和系统同时处理多种不同的编码系统。这不仅增加了开发和维护的复杂性,而且也增加了出错的风险。
    • 资源限制:在早期计算机技术中,内存和存储资源相对有限。不同的编码标准要求系统存储多套字符集数据,这无疑增加了对有限资源的消耗。
    • ……
  • 针对上述的种种问题,为了推行全球化,Unicode 应运而生,Unicode 的核心规则和设计原则是建立一个全球统一的字符集,使得世界上所有的文字和符号都能被唯一地识别和使用,无论使用者位于何地或使用何种语言。这套规则包括了字符的编码、表示、处理和转换机制,旨在确保不同系统和软件间能够无缝交换和处理文本数据。

    • 通用字符集 (UCS):Unicode 为每一个字符分配一个唯一的编号(称为“码点”)。这些码点被组织在一个统一的字符集中,官方称之为 “通用字符集”(Universal Character Set,UCS)。码点通常表示为 U+ 后跟一个十六进制数,例如:U+0041 代表大写的英文字母 “A”
    • 编码平面和区段:Unicode 码点被划分为多个 “平面(Planes)”,每个平面包含 65536(16^4)个码点。目前,Unicode定义了 17 个平面(从 0 到16),每个平面被分配了一个编号,从 “基本多文种平面(BMP)” 的 0 开始,到 16 号平面结束。这意味着 Unicode 理论上可以支持超过 110万(17*65536)个码点。
  • Unicode 仅仅只是字符集,给每个字符设置了唯一的数字编号而已,却没有给出这些数字编号实际如何存储,可以通过如下命令查看:

  • 为了在计算机系统中表示 Unicode 字符,定义了几种编码方案,这些方案包括 UTF-8、UTF-16 和 UTF-32 等。
    • UTF-8:使用 1 - 4 个字节表示每个 Unicode 字符,兼容 ASCII,是网络上最常用的编码。
    • UTF-16:使用 2 - 4 个字节表示每个 Unicode 字符,适合于需要经常处理基本多文种平面之外字符的应用。
    • UTF-32:使用固定的 4 个字节表示每个 Unicode 字符,简化了字符处理,但增加了存储空间的需求。
  • Unicode 字符集和对应的UTF-8 字符编码之间的关系,如下所示:

Released under the MIT License.

- + \ No newline at end of file diff --git a/notes/01_c-basic/04_xdx/index.html b/notes/01_c-basic/04_xdx/index.html index 736dff4..9686000 100644 --- a/notes/01_c-basic/04_xdx/index.html +++ b/notes/01_c-basic/04_xdx/index.html @@ -22,7 +22,7 @@ -
Skip to content

第一章:概述

  • 流程控制结构是用来控制程序中各语句执行顺序的语句,并且可以将语句组合成能完成一定功能小逻辑模块

  • 在程序设计中规定了三种流程结构,如下所示:

    • 顺序结构:程序从上到下逐行执行,中间没有任何判断和跳转。
    • 分支结构:根据条件,有选择的执行某段代码。在 C 语言中,有 if...elseswitch...case 两种分支语句。
    • 循环结构:根据循环条件,重复性的执行某段代码。在 C 语言中,有 forwhiledo...while 三种循环结构。
  • 在生活中的洗衣工厂,就包含了上述的三种流程结构,如下所示:

第二章:顺序结构

2.1 概述

  • 程序从上到下逐行地执行,表达式语句都是顺序执行的,并且上一行对某个变量的修改对下一行会产生影响。

2.2 应用示例

  • 示例:
c
#include <stdio.h>
+    
Skip to content

第一章:概述

  • 流程控制结构是用来控制程序中各语句执行顺序的语句,并且可以将语句组合成能完成一定功能小逻辑模块

  • 在程序设计中规定了三种流程结构,如下所示:

    • 顺序结构:程序从上到下逐行执行,中间没有任何判断和跳转。
    • 分支结构:根据条件,有选择的执行某段代码。在 C 语言中,有 if...elseswitch...case 两种分支语句。
    • 循环结构:根据循环条件,重复性的执行某段代码。在 C 语言中,有 forwhiledo...while 三种循环结构。
  • 在生活中的洗衣工厂,就包含了上述的三种流程结构,如下所示:

第二章:顺序结构

2.1 概述

  • 程序从上到下逐行地执行,表达式语句都是顺序执行的,并且上一行对某个变量的修改对下一行会产生影响。

2.2 应用示例

  • 示例:
c
#include <stdio.h>
 
 int main() {
 
@@ -774,7 +774,7 @@
 
     return 0;
 }

Released under the MIT License.

- + \ No newline at end of file diff --git a/notes/01_c-basic/05_xdx/index.html b/notes/01_c-basic/05_xdx/index.html index 401ed85..aa5481a 100644 --- a/notes/01_c-basic/05_xdx/index.html +++ b/notes/01_c-basic/05_xdx/index.html @@ -22,7 +22,7 @@ -
Skip to content

第一章:数组的概念

1.1 为什么需要数组?

1.1.1 需求分析 1

  • 需要统计某公司 50 个员工的工资情况,例如:计算平均工资、最高工资等。如果使用之前的知识,我们需要声明 50 个变量来分别记录每位员工的工资,即:
c
#include <stdio.h>
+    
Skip to content

第一章:数组的概念

1.1 为什么需要数组?

1.1.1 需求分析 1

  • 需要统计某公司 50 个员工的工资情况,例如:计算平均工资、最高工资等。如果使用之前的知识,我们需要声明 50 个变量来分别记录每位员工的工资,即:
c
#include <stdio.h>
 
 int main(){
     
@@ -722,7 +722,7 @@
 
     return 0;
 }

WARNING

在上述示例中,arr&arr 的值是一样的,但是对应的含义是不同的。

  • arr 是数组名,在大多数情况下会转换为数组第一个元素的地址,即:arr 等价于 &arr[0],其数据类型是 int *
  • &arr是数组名的地址,即整个数组的地址,它指向数组本身,并不是数组第一个元素的地址,&arr 的数据类型是 int(*)[3]

Released under the MIT License.

- + \ No newline at end of file diff --git a/notes/01_c-basic/06_xdx/index.html b/notes/01_c-basic/06_xdx/index.html index 94c9220..e6551ed 100644 --- a/notes/01_c-basic/06_xdx/index.html +++ b/notes/01_c-basic/06_xdx/index.html @@ -22,7 +22,7 @@ -
Skip to content

IMPORTANT

  • 指针是 C 语言中最重要的概念之一,也是最难以理解的概念之一。
  • 指针是 C 语言的精髓,要想掌握 C 语言就需要深入地了解指针。

第一章:颇具争议的指针

1.1 概述

  • 目前而言,操作系统几乎都是通过 C 语言来编写和维护的;而 C 语言提供了指针的用法,其能直接操作内存地址,是个非常强大灵活的工具;但是,需要开发者小心谨慎的使用,以确保程序的稳定性和安全性。

NOTE

之所以指针在 C 语言中颇具争议,是因为一方面其功能强大,直接操作内存地址;另一方面,又很危险,不正确的使用指针的方式,非常容易导致程序崩溃。

  • 如果没有能很好的使用指针,就会带来一系列的问题,如:

    • 空指针引用(Null Pointer Dereference):当一个指针没有正确初始化或者被赋予了空(NULL)值时,如果程序尝试访问该指针所指向的内存,会导致运行时错误,甚至导致程序崩溃。
    • 野指针(Dangling Pointers):指针指向的内存地址曾经分配给某个变量或对象,但后来该变量或对象被释放或者移动,导致指针仍指向已经无效的内存位置。对野指针进行操作可能会导致未定义的行为或程序崩溃。
    • 指针算术错误:在进行指针运算时,如果没有正确管理指针的偏移量或者超出了数组的边界,可能会导致指针指向错误的内存位置,从而影响程序的正确性和安全性。
    • 内存泄漏:如果动态分配的内存通过指针分配,但在不再需要时没有正确释放,会导致内存泄漏,长时间运行的程序可能会耗尽系统资源。
  • 为了减少指针带来的风险,开发人员可以采取以下的措施:

    • 良好的编程实践:确保指针的初始化和使用是安全的,避免空指针引用和野指针问题。
    • 边界检查:在进行指针运算时,始终确保不会超出数组或内存分配的边界。
    • 使用指针和引用的适当性:在可能的情况下,可以考虑使用更安全的语言特性,如:引用(在 C++ 等编程语言中)或者更高级别的数据结构来代替裸指针,从而减少指针使用时的潜在风险。

IMPORTANT

  • ① 既然指针很危险,那么通过一系列的手段将指针包装或屏蔽,以达到程序安全的目的(这是现代化的高级编程语言解决的思路,如:Java、Go、Rust 等)。
  • ② 之所以,指针还需要学习,是因为在嵌入式等领域,其机器的资源(CPU、内存等)非常有限;而现代化的高级编程语言虽然安全,但是需要的系统资源也庞大。
  • ③ 我们知道,编译型的程序不管编译过程如何复杂,至少需要两步:编译和运行。通常,我们也将这两步称为编译期和运行期。C 语言中的指针之所以危险就在于程序要在运行的时候才会发现问题(后知后觉);而现代化的高级编程语言中的编译器在程序编译的时候就会发现问题(提前发现问题)。
  • ④ C 语言的编译器之所以这么设计的原因,就在于当时的内存和 CPU 是非常有限(PDP-7 早期小型计算机,CPU:18 bit 的电子管逻辑,内存:4kb )和昂贵(72,000 $),如果加入安全限制的功能,会远远超过整个系统的资源。

1.2 现代化高级编程语言是如何解决指针危险的?

  • C++采用了如下的策略和机制,来解决指针危险操作的:

    • 智能指针: C++ 引入了智能指针(如std::shared_ptrstd::unique_ptr),这些指针提供了自动资源管理和所有权的语义。std::unique_ptr确保只有一个指针可以访问给定的资源,从而避免了传统指针的悬空引用和内存泄漏问题。std::shared_ptr允许多个指针共享一个资源,并在所有引用释放后自动释放。
    • 引用: C++ 中的引用(如:&符号)提供了更安全的间接访问方法,与指针相比,引用不能重新绑定到不同的对象,从而减少了意外的指针错误。
  • Go采用了如下的策略和机制,来解决指针危险操作的:

    • 内存管理和垃圾回收: Go 语言通过自动垃圾回收器管理内存,减少了手动内存管理所带来的指针操作错误。Go 的垃圾回收器定期扫描并释放不再使用的内存,避免了内存泄漏和悬空指针问题。
    • 指针的安全性: Go 语言的指针是受限的,不支持指针运算,从而减少了指针操作可能带来的风险。
  • Rust采用了如下的策略和机制,来解决指针危险操作的:

    • 所有权和借用: Rust 引入了所有权和借用的概念,编译器在编译时静态分析所有权转移和引用的生命周期。这种机制避免了数据竞争和空指针解引用等运行时错误,使得在编译时就能够保证内存安全。
    • 生命周期: Rust 的生命周期系统确保引用的有效性和安全性,防止了悬空引用和指针乱用。
  • Java采用了如下的策略和机制,来解决指针危险操作的:

    • 引用类型和自动内存管理: Java 中所有的对象引用都是通过引用来访问的,而不是直接的指针。Java 的自动垃圾回收器负责管理内存,从而避免了手动内存管理可能导致的指针错误,如:内存泄漏和悬空指针。
    • 强类型系统和异常处理: Java 的强类型系统和异常处理机制减少了指针操作带来的风险,如:空指针解引用异常(NullPointerException)。编译器在编译时能够捕获许多潜在的类型错误,进一步增强了程序的安全性和可靠性。

IMPORTANT

总而言之,各种编程语言通过引入不同的策略和机制,如:智能指针、垃圾回收器、所有权和借用,以及强类型系统,有效地减少了指针操作所带来的各种安全性和可靠性问题,提升了程序的稳定性和开发效率。

第二章:回顾知识

2.1 变量

  • 变量就是保存程序运行过程中临时产生的值,其语法如下:
c
数据类型 变量名 = 值 ;

IMPORTANT

变量名(标识符)需要符合命名规则和命名规范!!!

  • 强制规范:
    • ① 只能由小写大写英文字母0-9_ 组成。
    • ② 不能以数字开头。
    • ③ 不可以是关键字
    • ④ 标识符具有长度限制,不同编译器和平台会有所不同,一般限制在 63 个字符内。
    • ⑤ 严格区分大小写字母,如:Hello、hello 是不同的标识符。
  • 建议规范:
    • ① 为了提高阅读性,使用有意义的单词,见名知意,如:sum,name,max,year 等。
    • ② 使用下划线连接多个单词组成的标识符,如:max_classes_per_student 等。
    • ③ 多个单词组成的标识符,除了使用下划线连接,也可以使用小驼峰命名法,除第一个单词外,后续单词的首字母大写,如: studentId、student_name 等。
    • ④ 不要出现仅靠大小写区分不同的标识符,如:name、Name 容易混淆。
    • ⑤ 系统内部使用了一些下划线开头的标识符,如:C99 标准添加的类型 _Bool,为防止冲突,建议开发者尽量避免使用下划线开头的标识符。
  • 变量名作用,如下所示:
    • ① 当我们编写代码的时候,使用变量名关联某块内存的地址
    • ② 当 CPU 执行的时候,会将变量名替换为具体的地址,再进行具体的操作。

2.2 普通变量和指针变量的区别

  • 根据变量存储不同,我们可以将变量分为两类:
    • 普通变量:变量所对应的内存中存储的是普通值
    • 指针变量:变量所对应的内存中存储的是另一个变量的地址
  • 如下图所示:

img

  • 普通变量和指针变量的相同点,如下所示:
    • ① 普通变量有内存空间,指针变量也有内存空间。
    • ② 普通变量有内存地址,指针变量也有内存地址。
    • ③ 普通变量所对应的内存空间中有值,指针变量所对应的内存空间中也有值。
  • 普通变量和指针变量的不同点:
    • 普通变量所对应的内存空间存储的是普通的值,如:整数、小数、字符等;指针变量所对应的内存空间存储的是另外一个变量的地址
    • 普通变量有普通变量的运算方式,而指针变量有指针变量的运算方式(后续讲解)。

2.3 运算符

2.3.1 概述

  • 运算符是一种特殊的符号,用于数据的运算、赋值和比较等。
  • 表达式指的是一组运算数、运算符的组合,表达式一定具有值,一个变量或一个常量可以是表达式,变量、常量和运算符也可以组成表达式,如:

img

  • 操作数指的是参与运算或者对象,如:

  • 根据操作数个数,可以将运算符分为:
    • 一元运算符(一目运算符)。
    • 二元运算符(二目运算符)。
    • 三元运算符(三目运算符)。
  • 根据功能,可以将运算符分为:
    • 算术运算符。
    • 关系运算符(比较运算符)。
    • 逻辑运算符。
    • 赋值运算符。
    • 逻辑运算符。
    • 位运算符。
    • 三元运算符。

NOTE

掌握一个运算符,需要关注以下几个方面:

  • ① 运算符的含义。
  • ② 运算符操作数的个数。
  • ③ 运算符所组成的表达式。
  • ④ 运算符有无副作用,即:运算后是否会修改操作数的值。

IMPORTANT

普通变量支持上述的所有运算符;而指针变量并非支持上述的所有运算符,且支持运算符的含义和普通变量相差较大!!!

2.3.2 运算符的优先级

  • C 语言中运算符的优先级,如下所示:
优先级运算符名称或含义结合方向
1[]数组下标➡️(从左到右)
()圆括号
.成员选择(对象)
->成员选择(指针)
2-负号运算符⬅️(从右到左)
(类型)强制类型转换
++自增运算符
--自减运算符
*取值运算符
&取地址运算符
!逻辑非运算符
~按位取反运算符
sizeof长度运算符
3/➡️(从左到右)
*
%余数(取模)
4+➡️(从左到右)
-
5<<左移➡️(从左到右)
>>右移
6>大于➡️(从左到右)
>=大于等于
<小于
<=小于等于
7==等于➡️(从左到右)
!=不等于
8&按位与➡️(从左到右)
9^按位异或➡️(从左到右)
10|按位或➡️(从左到右)
11&&逻辑与➡️(从左到右)
12||逻辑或➡️(从左到右)
13?:条件运算符⬅️(从右到左)
14=赋值运算符⬅️(从右到左)
/=除后赋值
*=乘后赋值
%=取模后赋值
+=加后赋值
-=减后赋值
<<=左移后赋值
>>=右移后赋值
&=按位与后赋值
^=按位异或后赋值
|=按位或后赋值
15,逗号运算符➡️(从左到右)

WARNING

  • ① 不要过多的依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用小括号来控制表达式的执行顺序。
  • ② 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它分成几步来完成。
  • ③ 运算符优先级不用刻意地去记忆,总体上:一元运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 三元运算符 > 赋值运算符。

IMPORTANT

  • ① 取值运算符 * 和取地址运算符 & 的优先级相同,并且运算方向都是从右向左!!!
  • ② 逗号运算符 , 的优先级最低,并且运算方向是从左向右!!!

第三章:指针的理解和定义(⭐)

3.1 变量的访问方式

  • 计算机中程序的运行都是在内存中进行的,变量也是内存中分配的空间,且不同类型的变量占据的内存空间大小不同,如:char 类型的变量是 1 个字节,short 类型的变量是 2 个字节,int 类型的变量是 4 个字节...
  • 之前我们都是通过变量名(普通变量)访问内存中存储的数据,如下所示:
c
#include <stdio.h>
+    
Skip to content

IMPORTANT

  • 指针是 C 语言中最重要的概念之一,也是最难以理解的概念之一。
  • 指针是 C 语言的精髓,要想掌握 C 语言就需要深入地了解指针。

第一章:颇具争议的指针

1.1 概述

  • 目前而言,操作系统几乎都是通过 C 语言来编写和维护的;而 C 语言提供了指针的用法,其能直接操作内存地址,是个非常强大灵活的工具;但是,需要开发者小心谨慎的使用,以确保程序的稳定性和安全性。

NOTE

之所以指针在 C 语言中颇具争议,是因为一方面其功能强大,直接操作内存地址;另一方面,又很危险,不正确的使用指针的方式,非常容易导致程序崩溃。

  • 如果没有能很好的使用指针,就会带来一系列的问题,如:

    • 空指针引用(Null Pointer Dereference):当一个指针没有正确初始化或者被赋予了空(NULL)值时,如果程序尝试访问该指针所指向的内存,会导致运行时错误,甚至导致程序崩溃。
    • 野指针(Dangling Pointers):指针指向的内存地址曾经分配给某个变量或对象,但后来该变量或对象被释放或者移动,导致指针仍指向已经无效的内存位置。对野指针进行操作可能会导致未定义的行为或程序崩溃。
    • 指针算术错误:在进行指针运算时,如果没有正确管理指针的偏移量或者超出了数组的边界,可能会导致指针指向错误的内存位置,从而影响程序的正确性和安全性。
    • 内存泄漏:如果动态分配的内存通过指针分配,但在不再需要时没有正确释放,会导致内存泄漏,长时间运行的程序可能会耗尽系统资源。
  • 为了减少指针带来的风险,开发人员可以采取以下的措施:

    • 良好的编程实践:确保指针的初始化和使用是安全的,避免空指针引用和野指针问题。
    • 边界检查:在进行指针运算时,始终确保不会超出数组或内存分配的边界。
    • 使用指针和引用的适当性:在可能的情况下,可以考虑使用更安全的语言特性,如:引用(在 C++ 等编程语言中)或者更高级别的数据结构来代替裸指针,从而减少指针使用时的潜在风险。

IMPORTANT

  • ① 既然指针很危险,那么通过一系列的手段将指针包装或屏蔽,以达到程序安全的目的(这是现代化的高级编程语言解决的思路,如:Java、Go、Rust 等)。
  • ② 之所以,指针还需要学习,是因为在嵌入式等领域,其机器的资源(CPU、内存等)非常有限;而现代化的高级编程语言虽然安全,但是需要的系统资源也庞大。
  • ③ 我们知道,编译型的程序不管编译过程如何复杂,至少需要两步:编译和运行。通常,我们也将这两步称为编译期和运行期。C 语言中的指针之所以危险就在于程序要在运行的时候才会发现问题(后知后觉);而现代化的高级编程语言中的编译器在程序编译的时候就会发现问题(提前发现问题)。
  • ④ C 语言的编译器之所以这么设计的原因,就在于当时的内存和 CPU 是非常有限(PDP-7 早期小型计算机,CPU:18 bit 的电子管逻辑,内存:4kb )和昂贵(72,000 $),如果加入安全限制的功能,会远远超过整个系统的资源。

1.2 现代化高级编程语言是如何解决指针危险的?

  • C++采用了如下的策略和机制,来解决指针危险操作的:

    • 智能指针: C++ 引入了智能指针(如std::shared_ptrstd::unique_ptr),这些指针提供了自动资源管理和所有权的语义。std::unique_ptr确保只有一个指针可以访问给定的资源,从而避免了传统指针的悬空引用和内存泄漏问题。std::shared_ptr允许多个指针共享一个资源,并在所有引用释放后自动释放。
    • 引用: C++ 中的引用(如:&符号)提供了更安全的间接访问方法,与指针相比,引用不能重新绑定到不同的对象,从而减少了意外的指针错误。
  • Go采用了如下的策略和机制,来解决指针危险操作的:

    • 内存管理和垃圾回收: Go 语言通过自动垃圾回收器管理内存,减少了手动内存管理所带来的指针操作错误。Go 的垃圾回收器定期扫描并释放不再使用的内存,避免了内存泄漏和悬空指针问题。
    • 指针的安全性: Go 语言的指针是受限的,不支持指针运算,从而减少了指针操作可能带来的风险。
  • Rust采用了如下的策略和机制,来解决指针危险操作的:

    • 所有权和借用: Rust 引入了所有权和借用的概念,编译器在编译时静态分析所有权转移和引用的生命周期。这种机制避免了数据竞争和空指针解引用等运行时错误,使得在编译时就能够保证内存安全。
    • 生命周期: Rust 的生命周期系统确保引用的有效性和安全性,防止了悬空引用和指针乱用。
  • Java采用了如下的策略和机制,来解决指针危险操作的:

    • 引用类型和自动内存管理: Java 中所有的对象引用都是通过引用来访问的,而不是直接的指针。Java 的自动垃圾回收器负责管理内存,从而避免了手动内存管理可能导致的指针错误,如:内存泄漏和悬空指针。
    • 强类型系统和异常处理: Java 的强类型系统和异常处理机制减少了指针操作带来的风险,如:空指针解引用异常(NullPointerException)。编译器在编译时能够捕获许多潜在的类型错误,进一步增强了程序的安全性和可靠性。

IMPORTANT

总而言之,各种编程语言通过引入不同的策略和机制,如:智能指针、垃圾回收器、所有权和借用,以及强类型系统,有效地减少了指针操作所带来的各种安全性和可靠性问题,提升了程序的稳定性和开发效率。

第二章:回顾知识

2.1 变量

  • 变量就是保存程序运行过程中临时产生的值,其语法如下:
c
数据类型 变量名 = 值 ;

IMPORTANT

变量名(标识符)需要符合命名规则和命名规范!!!

  • 强制规范:
    • ① 只能由小写大写英文字母0-9_ 组成。
    • ② 不能以数字开头。
    • ③ 不可以是关键字
    • ④ 标识符具有长度限制,不同编译器和平台会有所不同,一般限制在 63 个字符内。
    • ⑤ 严格区分大小写字母,如:Hello、hello 是不同的标识符。
  • 建议规范:
    • ① 为了提高阅读性,使用有意义的单词,见名知意,如:sum,name,max,year 等。
    • ② 使用下划线连接多个单词组成的标识符,如:max_classes_per_student 等。
    • ③ 多个单词组成的标识符,除了使用下划线连接,也可以使用小驼峰命名法,除第一个单词外,后续单词的首字母大写,如: studentId、student_name 等。
    • ④ 不要出现仅靠大小写区分不同的标识符,如:name、Name 容易混淆。
    • ⑤ 系统内部使用了一些下划线开头的标识符,如:C99 标准添加的类型 _Bool,为防止冲突,建议开发者尽量避免使用下划线开头的标识符。
  • 变量名作用,如下所示:
    • ① 当我们编写代码的时候,使用变量名关联某块内存的地址
    • ② 当 CPU 执行的时候,会将变量名替换为具体的地址,再进行具体的操作。

2.2 普通变量和指针变量的区别

  • 根据变量存储不同,我们可以将变量分为两类:
    • 普通变量:变量所对应的内存中存储的是普通值
    • 指针变量:变量所对应的内存中存储的是另一个变量的地址
  • 如下图所示:

img

  • 普通变量和指针变量的相同点,如下所示:
    • ① 普通变量有内存空间,指针变量也有内存空间。
    • ② 普通变量有内存地址,指针变量也有内存地址。
    • ③ 普通变量所对应的内存空间中有值,指针变量所对应的内存空间中也有值。
  • 普通变量和指针变量的不同点:
    • 普通变量所对应的内存空间存储的是普通的值,如:整数、小数、字符等;指针变量所对应的内存空间存储的是另外一个变量的地址
    • 普通变量有普通变量的运算方式,而指针变量有指针变量的运算方式(后续讲解)。

2.3 运算符

2.3.1 概述

  • 运算符是一种特殊的符号,用于数据的运算、赋值和比较等。
  • 表达式指的是一组运算数、运算符的组合,表达式一定具有值,一个变量或一个常量可以是表达式,变量、常量和运算符也可以组成表达式,如:

img

  • 操作数指的是参与运算或者对象,如:

  • 根据操作数个数,可以将运算符分为:
    • 一元运算符(一目运算符)。
    • 二元运算符(二目运算符)。
    • 三元运算符(三目运算符)。
  • 根据功能,可以将运算符分为:
    • 算术运算符。
    • 关系运算符(比较运算符)。
    • 逻辑运算符。
    • 赋值运算符。
    • 逻辑运算符。
    • 位运算符。
    • 三元运算符。

NOTE

掌握一个运算符,需要关注以下几个方面:

  • ① 运算符的含义。
  • ② 运算符操作数的个数。
  • ③ 运算符所组成的表达式。
  • ④ 运算符有无副作用,即:运算后是否会修改操作数的值。

IMPORTANT

普通变量支持上述的所有运算符;而指针变量并非支持上述的所有运算符,且支持运算符的含义和普通变量相差较大!!!

2.3.2 运算符的优先级

  • C 语言中运算符的优先级,如下所示:
优先级运算符名称或含义结合方向
1[]数组下标➡️(从左到右)
()圆括号
.成员选择(对象)
->成员选择(指针)
2-负号运算符⬅️(从右到左)
(类型)强制类型转换
++自增运算符
--自减运算符
*取值运算符
&取地址运算符
!逻辑非运算符
~按位取反运算符
sizeof长度运算符
3/➡️(从左到右)
*
%余数(取模)
4+➡️(从左到右)
-
5<<左移➡️(从左到右)
>>右移
6>大于➡️(从左到右)
>=大于等于
<小于
<=小于等于
7==等于➡️(从左到右)
!=不等于
8&按位与➡️(从左到右)
9^按位异或➡️(从左到右)
10|按位或➡️(从左到右)
11&&逻辑与➡️(从左到右)
12||逻辑或➡️(从左到右)
13?:条件运算符⬅️(从右到左)
14=赋值运算符⬅️(从右到左)
/=除后赋值
*=乘后赋值
%=取模后赋值
+=加后赋值
-=减后赋值
<<=左移后赋值
>>=右移后赋值
&=按位与后赋值
^=按位异或后赋值
|=按位或后赋值
15,逗号运算符➡️(从左到右)

WARNING

  • ① 不要过多的依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用小括号来控制表达式的执行顺序。
  • ② 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它分成几步来完成。
  • ③ 运算符优先级不用刻意地去记忆,总体上:一元运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 三元运算符 > 赋值运算符。

IMPORTANT

  • ① 取值运算符 * 和取地址运算符 & 的优先级相同,并且运算方向都是从右向左!!!
  • ② 逗号运算符 , 的优先级最低,并且运算方向是从左向右!!!

第三章:指针的理解和定义(⭐)

3.1 变量的访问方式

  • 计算机中程序的运行都是在内存中进行的,变量也是内存中分配的空间,且不同类型的变量占据的内存空间大小不同,如:char 类型的变量是 1 个字节,short 类型的变量是 2 个字节,int 类型的变量是 4 个字节...
  • 之前我们都是通过变量名(普通变量)访问内存中存储的数据,如下所示:
c
#include <stdio.h>
 
 int main() {
 
@@ -103,7 +103,7 @@
 
 printf("Address of array: %p\n", &arr);  // 返回整个数组的地址
 printf("Address of pointer: %p\n", &ptr);  // 返回指针变量ptr的地址

综上所述,通过这些示例和解释,可以看出数组名虽然在某些场合下可以像指针一样使用,但它并不是一个真正的指针变量,而是一个常量,表示数组的首地址。

Released under the MIT License.

- + \ No newline at end of file diff --git a/notes/04_linux/01_xdx/index.html b/notes/04_linux/01_xdx/index.html index fc876bd..a143449 100644 --- a/notes/04_linux/01_xdx/index.html +++ b/notes/04_linux/01_xdx/index.html @@ -22,8 +22,8 @@ -
Skip to content

第一章:Linux

1.1 Linux 概述

  • Linux 是一种开源的操作系统,最初由芬兰的林纳斯·托瓦兹(Linus Torvalds)开发。它基于 UNIX 操作系统,并且具有高度的可定制性和灵活性。Linux 操作系统被广泛应用于服务器、嵌入式系统和个人计算机等领域。
  • 它具有稳定性、安全性和可靠性,并且支持多用户、多任务和多线程。Linux 拥有众多的发行版,如:Ubuntu、Red Hat、Debian 等,每个发行版都有自己的特点和优势。
  • 由于其开源性质,Linux 操作系统受到了全球开发者的广泛支持和贡献,成为了计算机行业中的重要组成部分。

1.2 Linux 的发展史

  • Linux 的发展历史可以分为以下几个阶段:

    • ① 初始阶段(1991 - 1994 年):林纳斯·托瓦兹在 1991 年发布了 Linux 内核的第一个版本,并将其开源。在接下来的几年里,Linux 逐渐吸引了一些开发者的关注和参与,开始逐步完善和扩展功能。
    • ② 发展阶段(1995 - 2000 年):在这个阶段,Linux 开始受到更多人的关注和认可。许多开发者和公司开始为 Linux 开发应用程序和驱动程序,为其增加更多的功能和兼容性。同时,一些发行版如:Red Hat、Debian 等也开始出现,为用户提供了更方便的安装和使用方式。
    • ③ 商业化阶段(2001 - 至今):随着 Linux 的成熟和广泛应用,越来越多的公司开始将 Linux 作为服务器和嵌入式设备的操作系统。一些大型科技公司,如:IBM、Oracle 等也开始投入大量资源支持 Linux 的发展。同时,一些商业化的 Linux 发行版,如:SUSE、Ubuntu 等也崭露头角,为企业和个人用户提供了更专业的支持和服务。
    • ④ 社区发展阶段:Linux 的发展一直依赖于全球开发者社区的贡献和支持。Linux 社区不断壮大,吸引了众多的开发者和爱好者参与其中。通过社区的力量,Linux 不断更新迭代,推出了许多新的版本和功能。
  • 总的来说,Linux 的发展历程是一个由个人项目逐渐发展为全球开源社区支持的过程。它的成功得益于开源模式的优势,以及全球开发者的共同努力和贡献。

1.3 Linux 的组成(⭐)

  • Linux 主要由以下几个组成部分构成:

    • Linux 内核:Linux 内核是整个操作系统的核心,负责管理硬件设备、内存管理、进程调度等核心功能。它是由林纳斯·托瓦兹及其他开发者编写和维护的。
    • Shell 解释器:Shell 解释器是用户与操作系统交互的接口,它接收用户输入的命令并将其解释执行。常见的 Shell 解释器有 Bash、Zsh 等,它们提供了命令行界面和脚本编程功能。
    • 外围的应用程序:命令、应用程序、图形化界面……
  • 其图示如下:

image-20240115214505877

  • 上述的组成部分共同构成了一个完整的 Linux 操作系统,为用户提供了丰富的功能和灵活性。

1.4 Linux 发行版本(⭐)

  • Linux 发行版本就是:Linux 内核 + 命令解释器 + 应用程序(桌面)
  • 主流的 Linux 发行版本如下:
Linux 系统类别Linux 系统备注
Debian 系列Debian更新频率较低,较为稳定和安全,可以用于企业生产环境。
Ubuntu桌面美观,使用方便,开发使用。有桌面版和企业版本(服务器版本)。
Redhat 系列RedHat Enterprise Linux(RHEL红帽企业版本
CentOS基于 Red Hat Enterprise Linux(RHEL)源代码构建的免费开源操作系统。它提供了企业级的稳定性和安全性,广泛用于服务器环境。
FedoraFedora 是由 Red Hat 赞助的社区驱动的 Linux 发行版,注重最新的软件和技术。它提供了一个先进的桌面环境和开发者工具。
Rocky Linux用来替代 CentOS 系统的,也是基于 Red Hat Enterprise Linux(RHEL)源代码构建的免费开源操作系统。
Alma Linux用来替代 CentOS 系统的,也是基于 Red Hat Enterprise Linux(RHEL)源代码构建的免费开源操作系统。
其它系列SUSE、OpenSUSEOpenSUSE 是一个用户友好且功能强大的 Linux 发行版,具有稳定性和灵活性。它提供了多种桌面环境和服务器选项。
  • 当然,除了以上几个主流的 Linux 发行版,还有许多其他的发行版,如:Arch Linux、Gentoo、Mageia 等,它们各自有着不同的特点和适用场景。
  • 选择适合自己需求的发行版是根据个人或组织的需求和偏好来决定的。

1.5 Linux 版本选择(⭐)

  • 推荐选择 LTS 版稳定版

WARNING

  • LTS 是 "Long-Term Support" 的缩写,意为长期支持。在软件开发领域,LTS 通常用来描述某个版本或发行版的长期支持周期。
  • 对于 Linux 发行版或其他软件,LTS 版本通常会提供更长时间的支持和维护,以确保稳定性和安全性。这意味着在 LTS 版本的支持周期内,开发者会持续提供安全补丁、错误修复和其他重要更新,以保持系统的稳定性和可靠性。
  • LTS 版本通常适用于企业和组织等需要长期稳定性和可靠性的环境。相比于非 LTS 版本,LTS 版本的更新频率较低,更注重于提供长期支持和维护。
  • 本次选择:
系统版本说明
UbuntuLTS 18.04 、LTS 20.04 等
AlmaLinux9.1、9.2、9.3 等

第二章:工作和学习环境部署(⭐)

2.1 服务器

  • 服务器是一种专门用于提供服务的计算机系统。它通常具有更高的性能、可靠性和稳定性,以满足处理大量请求和提供持续服务的需求。
  • 服务器的主要功能是接收来自客户端的请求,并提供相应的服务或资源。这些服务可以包括:网站托管、数据库管理、文件存储、电子邮件、应用程序运行等。服务器通过网络与客户端进行通信,处理请求并返回相应的数据或结果。
  • 服务器通常采用高性能的硬件配置,如:多核处理器、大容量内存、高速存储设备等,以确保能够处理大量的并发请求。它们还通常具有冗余的设计,包括冗余电源、冗余网络连接和冗余存储等,以提高可靠性和可用性。
  • 服务器可以是物理服务器,即实际的硬件设备,也可以是虚拟服务器,即在物理服务器上通过虚拟化技术创建的虚拟机。无论是物理服务器还是虚拟服务器,它们都扮演着提供服务和资源的角色。
  • 在企业和组织中,服务器通常由专门的 IT 团队进行管理和维护。他们负责服务器的配置、安全性、性能优化、备份和恢复等工作,以确保服务器的稳定运行和数据的安全性。

TIP

实际工作的时候,Linux 系统会运行在服务器上。

2.2 虚拟机概述

  • 虚拟机(Virtual Machine,简称 VM)是一种软件实现的计算机系统,它在物理计算机上模拟出一个完整的计算环境。虚拟机可以在同一台物理计算机上同时运行多个独立的操作系统和应用程序。

2

  • 虚拟机的工作原理是通过虚拟化技术将物理计算机的硬件资源(如:处理器、内存、存储等)进行抽象和分配,为每个虚拟机提供一部分资源。每个虚拟机都被视为一个独立的计算机系统,可以运行自己的操作系统和应用程序。
  • 虚拟机的优势在于它可以提供隔离性灵活性。通过虚拟机,可以在同一台物理计算机上同时运行多个操作系统,实现资源的共享和最大化利用。同时,虚拟机还可以提供快速部署、快速备份和恢复等功能,方便管理和维护。
  • 常见的虚拟机软件,包括:VMware、VirtualBox、KVM 等。它们提供了虚拟化平台和管理工具,使用户可以轻松创建、配置和管理虚拟机。虚拟机广泛应用于开发和测试环境、服务器虚拟化、云计算等领域。

WARNING

虚拟机软件虚拟机的概念不同:

  • 虚拟机软件是用来模拟硬件一个软件,如:VMware 等。
  • ② 而虚拟机是通过虚拟机软件模拟出来的计算机硬件,其实是文件的集合,相当于一台没有安装 Windows 操作系统的裸机
  • ③ 在现实交谈的时候,我们有时候会模糊虚拟机软件虚拟机的概念,甚至会使用虚拟机来代替虚拟机软件;此时,就需要根据上下文环境(语境)来判断到底说的是虚拟机软件还是虚拟机了。

2.3 安装虚拟机软件

2.3.1 前提条件

  • 需要在 BIOS 中开启虚拟化功能。

image-20240117085245337

2.3.2 安装步骤

  • ① 双击打开 VMware 安装程序 。

双击打开VMware安装程序.png

  • ② 进行下一步安装:

VMware进行下一步安装.png

  • ③ 同意许可协议,单击下一步:

VMware同意许可协议,单击下一步.png

  • ④ 根据需要决定是否需要更改软件的安装位置(建议放置于除 C 盘以外任意盘符下):

VMware更改安装位置.png

VMware更改安装位置成功.png

  • ⑤ 更改成功后,单击确定,下一步继续安装:

VMware更改成功后,单击确定,下一步继续安装.png

  • ⑥ 用户体验设置,如下图所示,单击下一步继续安装:

VMware用户体验设置,如下图所示,单击下一步继续安装.png

  • ⑦ 快捷方式设置,单击下一步继续安装:

VMware快捷方式设置,单击下一步继续安装.png

  • ⑧ 单击安装按钮:

VMware单击安装按钮.png

  • ⑨ VMware 输入许可证:

VMware单击许可证.png

VMware输入许可证.png

  • ⑩ 安装结束后,单击完成按钮:

VMware安装结束后,单击完成按钮.png

  • ⑪ 检查虚拟机软件是否安装了虚拟网卡:

查看VMware安装的虚拟网卡.png

查看VMware安装的虚拟网卡1.png

查看VMware安装的虚拟网卡2.png

2.3.2 配置网络

  • ① 打开 VMware 虚拟机软件:

image-20240116202917529

  • ② 编辑 → 虚拟网络编辑器:

image-20240116202955131

  • ③ Vmnet8 → 更改设置:

image-20240116203207282

  • ④ 更改子网 IP 地址为 :192.168.10.0 ,其目的是为了将 IP 固定。

image-20240116203357894

  • ⑤ DHCP 设置:

image-20240116203529749

image-20240116203627959

  • ⑤ 通过 cmd ,输入 ipconfig 命令,查看是否配置成功:

2.4 创建虚拟机

2.4.1 概述

  • 创建虚拟机,本质上就类似购买一台没有安装操作系统的裸机

2.4.2 创建虚拟机

  • ① 文件 → 新建虚拟机:

image-20240117090352182

  • ② 选择自定义类型的配置:

image-20240117090443216

  • ③ 虚拟机硬件兼容性:下一步即可。

image-20240117090529266

  • ④ 选择稍后安装操作系统

image-20240117090636337

  • ⑤ 选择虚拟机将安装的操作系统:

image-20240117090805295

  • ⑥ 设置虚拟机的名称安装位置

image-20240117090944676

WARNING

一个虚拟机一个安装目录(文件夹),防止引起文件的冲突。

  • ⑦ 虚拟机中处理器的配置:下一步即可。

image-20240117091051284

  • ⑧ 设置虚拟机的内存:至少 2048 MB以上。

image-20240117091202131

  • ⑨ 设置虚拟机的网络类型:下一步即可。

image-20240117091257738

  • ⑩ 设置 I/O 控制器类型:下一步即可。

image-20240117091402913

  • ⑪ 选择磁盘类型:下一步即可。

image-20240117091540264

  • ⑫ 选择磁盘:下一步即可。

image-20240117091640870

  • ⑬ 选择磁盘容量:调整为 40 GB。

image-20240117091832846

  • ⑭ 指定磁盘文件:下一步即可。

image-20240117091907233

  • ⑮ 创建虚拟机完毕:

image-20240117092013264

  • ⑯ 查看是否创建虚拟机成功:

image-20240117092101810

2.4.3 虚拟机归类(分类)

  • 实际情况下,我们可能会创建很多虚拟机,VMware 提供了文件夹的功能来管理虚拟机;其步骤如下所示:
  • ① 鼠标右键 → 创建文件夹:

image-20240117092324545

  • ② 修改文件夹的名称:

image-20240117092600931

image-20240117092643086

image-20240117092720769

  • ③ 将刚才创建的虚拟机到该文件夹下:

2.4.4 设置 CD/DVD

  • 以前,我们在一台裸机上安装操作系统的时候,需要通过 DVD 或 U 盘将操作系统的 ISO 镜像文件,安装到裸机上;
  • 同理,在使用虚拟机软件的时候,也需要此类步骤;其步骤如下:
  • ① 编辑虚拟机设置:

image-20240117093143947

  • ② 选择硬盘上的 ISO 镜像文件:

image-20240117093354461

  • ③ 查看是否配置成功:

image-20240117093435976

2.5 安装 Linux

  • 开启此虚拟机

image-20240117093516070

  • 鼠标点击进去之后,通过键盘上的方向键来选择:

image-20240117093610205

  • 注意⚠️:键盘上的方向键在这里

image-20240117093918602

  • ③ 设置操作系统的语言环境为中文

image-20240117094530342

  • ④ 设置系统安装目的地

  • ⑤ 设置软件选择:默认即可

  • ⑥ 设置 root 的密码:123456即可

WARNING

学习阶段无所谓设置什么密码,但是生产环境,必须复杂并且经常更换!!!

  • ⑦ 配置网络和主机名

image-20240224223931266

image-20240224224038036

image-20240224224138061

image-20240224224209724

image-20240224224245924

image-20240224224344051

  • ⑧ 查看配置网络和主机名是否成功:

image-20240224224420273

  • ⑨ 点击开始安装:漫长的等待……

  • ⑩ 安装完成之后,会提示重启系统,那就重启吧:

2.6 远程连接 Linux

2.6.1 查看 Linux 的 IP 地址

  • 通过 ifconfig 命令来查看 Linux 的 IP 地址:
shell
ifconfig

image-20240117101543732

2.6.2 远程连接 Linux

  • 可以通过 xshell 之类的远程连接工具来连接 Linux ,其步骤如下:
  • ① 新建会话:

image-20240117101749340

  • ② 输入 Linux 的 IP 地址:

image-20240117101906927

  • ③ 输入用户名和密码:

image-20240117102005340

  • ④ 接收和保存远程 Linux 的密钥:

image-20240117102123845

  • ⑤ 查看是否登录成功:

image-20240117102159684

Released under the MIT License.

- +
Skip to content

第一章:Linux

1.1 Linux 概述

  • Linux 是一种开源的操作系统,最初由芬兰的林纳斯·托瓦兹(Linus Torvalds)开发。它基于 UNIX 操作系统,并且具有高度的可定制性和灵活性。Linux 操作系统被广泛应用于服务器、嵌入式系统和个人计算机等领域。
  • 它具有稳定性、安全性和可靠性,并且支持多用户、多任务和多线程。Linux 拥有众多的发行版,如:Ubuntu、Red Hat、Debian 等,每个发行版都有自己的特点和优势。
  • 由于其开源性质,Linux 操作系统受到了全球开发者的广泛支持和贡献,成为了计算机行业中的重要组成部分。

1.2 Linux 的发展史

  • Linux 的发展历史可以分为以下几个阶段:

    • ① 初始阶段(1991 - 1994 年):林纳斯·托瓦兹在 1991 年发布了 Linux 内核的第一个版本,并将其开源。在接下来的几年里,Linux 逐渐吸引了一些开发者的关注和参与,开始逐步完善和扩展功能。
    • ② 发展阶段(1995 - 2000 年):在这个阶段,Linux 开始受到更多人的关注和认可。许多开发者和公司开始为 Linux 开发应用程序和驱动程序,为其增加更多的功能和兼容性。同时,一些发行版如:Red Hat、Debian 等也开始出现,为用户提供了更方便的安装和使用方式。
    • ③ 商业化阶段(2001 - 至今):随着 Linux 的成熟和广泛应用,越来越多的公司开始将 Linux 作为服务器和嵌入式设备的操作系统。一些大型科技公司,如:IBM、Oracle 等也开始投入大量资源支持 Linux 的发展。同时,一些商业化的 Linux 发行版,如:SUSE、Ubuntu 等也崭露头角,为企业和个人用户提供了更专业的支持和服务。
    • ④ 社区发展阶段:Linux 的发展一直依赖于全球开发者社区的贡献和支持。Linux 社区不断壮大,吸引了众多的开发者和爱好者参与其中。通过社区的力量,Linux 不断更新迭代,推出了许多新的版本和功能。
  • 总的来说,Linux 的发展历程是一个由个人项目逐渐发展为全球开源社区支持的过程。它的成功得益于开源模式的优势,以及全球开发者的共同努力和贡献。

1.3 Linux 的组成(⭐)

  • Linux 主要由以下几个组成部分构成:

    • Linux 内核:Linux 内核是整个操作系统的核心,负责管理硬件设备、内存管理、进程调度等核心功能。它是由林纳斯·托瓦兹及其他开发者编写和维护的。
    • Shell 解释器:Shell 解释器是用户与操作系统交互的接口,它接收用户输入的命令并将其解释执行。常见的 Shell 解释器有 Bash、Zsh 等,它们提供了命令行界面和脚本编程功能。
    • 外围的应用程序:命令、应用程序、图形化界面……
  • 其图示如下:

image-20240115214505877

  • 上述的组成部分共同构成了一个完整的 Linux 操作系统,为用户提供了丰富的功能和灵活性。

1.4 Linux 发行版本(⭐)

  • Linux 发行版本就是:Linux 内核 + 命令解释器 + 应用程序(桌面)
  • 主流的 Linux 发行版本如下:
Linux 系统类别Linux 系统备注
Debian 系列Debian更新频率较低,较为稳定和安全,可以用于企业生产环境。
Ubuntu桌面美观,使用方便,开发使用。有桌面版和企业版本(服务器版本)。
Redhat 系列RedHat Enterprise Linux(RHEL红帽企业版本
CentOS基于 Red Hat Enterprise Linux(RHEL)源代码构建的免费开源操作系统。它提供了企业级的稳定性和安全性,广泛用于服务器环境。
FedoraFedora 是由 Red Hat 赞助的社区驱动的 Linux 发行版,注重最新的软件和技术。它提供了一个先进的桌面环境和开发者工具。
Rocky Linux用来替代 CentOS 系统的,也是基于 Red Hat Enterprise Linux(RHEL)源代码构建的免费开源操作系统。
Alma Linux用来替代 CentOS 系统的,也是基于 Red Hat Enterprise Linux(RHEL)源代码构建的免费开源操作系统。
其它系列SUSE、OpenSUSEOpenSUSE 是一个用户友好且功能强大的 Linux 发行版,具有稳定性和灵活性。它提供了多种桌面环境和服务器选项。
  • 当然,除了以上几个主流的 Linux 发行版,还有许多其他的发行版,如:Arch Linux、Gentoo、Mageia 等,它们各自有着不同的特点和适用场景。
  • 选择适合自己需求的发行版是根据个人或组织的需求和偏好来决定的。

1.5 Linux 版本选择(⭐)

  • 推荐选择 LTS 版稳定版

WARNING

  • LTS 是 "Long-Term Support" 的缩写,意为长期支持。在软件开发领域,LTS 通常用来描述某个版本或发行版的长期支持周期。
  • 对于 Linux 发行版或其他软件,LTS 版本通常会提供更长时间的支持和维护,以确保稳定性和安全性。这意味着在 LTS 版本的支持周期内,开发者会持续提供安全补丁、错误修复和其他重要更新,以保持系统的稳定性和可靠性。
  • LTS 版本通常适用于企业和组织等需要长期稳定性和可靠性的环境。相比于非 LTS 版本,LTS 版本的更新频率较低,更注重于提供长期支持和维护。
  • 本次选择:
系统版本说明
UbuntuLTS 18.04 、LTS 20.04 等
AlmaLinux9.1、9.2、9.3 等

第二章:工作和学习环境部署(⭐)

2.1 服务器

  • 服务器是一种专门用于提供服务的计算机系统。它通常具有更高的性能、可靠性和稳定性,以满足处理大量请求和提供持续服务的需求。
  • 服务器的主要功能是接收来自客户端的请求,并提供相应的服务或资源。这些服务可以包括:网站托管、数据库管理、文件存储、电子邮件、应用程序运行等。服务器通过网络与客户端进行通信,处理请求并返回相应的数据或结果。
  • 服务器通常采用高性能的硬件配置,如:多核处理器、大容量内存、高速存储设备等,以确保能够处理大量的并发请求。它们还通常具有冗余的设计,包括冗余电源、冗余网络连接和冗余存储等,以提高可靠性和可用性。
  • 服务器可以是物理服务器,即实际的硬件设备,也可以是虚拟服务器,即在物理服务器上通过虚拟化技术创建的虚拟机。无论是物理服务器还是虚拟服务器,它们都扮演着提供服务和资源的角色。
  • 在企业和组织中,服务器通常由专门的 IT 团队进行管理和维护。他们负责服务器的配置、安全性、性能优化、备份和恢复等工作,以确保服务器的稳定运行和数据的安全性。

TIP

实际工作的时候,Linux 系统会运行在服务器上。

2.2 虚拟机概述

  • 虚拟机(Virtual Machine,简称 VM)是一种软件实现的计算机系统,它在物理计算机上模拟出一个完整的计算环境。虚拟机可以在同一台物理计算机上同时运行多个独立的操作系统和应用程序。

2

  • 虚拟机的工作原理是通过虚拟化技术将物理计算机的硬件资源(如:处理器、内存、存储等)进行抽象和分配,为每个虚拟机提供一部分资源。每个虚拟机都被视为一个独立的计算机系统,可以运行自己的操作系统和应用程序。
  • 虚拟机的优势在于它可以提供隔离性灵活性。通过虚拟机,可以在同一台物理计算机上同时运行多个操作系统,实现资源的共享和最大化利用。同时,虚拟机还可以提供快速部署、快速备份和恢复等功能,方便管理和维护。
  • 常见的虚拟机软件,包括:VMware、VirtualBox、KVM 等。它们提供了虚拟化平台和管理工具,使用户可以轻松创建、配置和管理虚拟机。虚拟机广泛应用于开发和测试环境、服务器虚拟化、云计算等领域。

WARNING

虚拟机软件虚拟机的概念不同:

  • 虚拟机软件是用来模拟硬件一个软件,如:VMware 等。
  • ② 而虚拟机是通过虚拟机软件模拟出来的计算机硬件,其实是文件的集合,相当于一台没有安装 Windows 操作系统的裸机
  • ③ 在现实交谈的时候,我们有时候会模糊虚拟机软件虚拟机的概念,甚至会使用虚拟机来代替虚拟机软件;此时,就需要根据上下文环境(语境)来判断到底说的是虚拟机软件还是虚拟机了。

2.3 安装虚拟机软件

2.3.1 前提条件

  • 需要在 BIOS 中开启虚拟化功能。

image-20240117085245337

2.3.2 安装步骤

  • ① 双击打开 VMware 安装程序 。

双击打开VMware安装程序.png

  • ② 进行下一步安装:

VMware进行下一步安装.png

  • ③ 同意许可协议,单击下一步:

VMware同意许可协议,单击下一步.png

  • ④ 根据需要决定是否需要更改软件的安装位置(建议放置于除 C 盘以外任意盘符下):

VMware更改安装位置.png

VMware更改安装位置成功.png

  • ⑤ 更改成功后,单击确定,下一步继续安装:

VMware更改成功后,单击确定,下一步继续安装.png

  • ⑥ 用户体验设置,如下图所示,单击下一步继续安装:

VMware用户体验设置,如下图所示,单击下一步继续安装.png

  • ⑦ 快捷方式设置,单击下一步继续安装:

VMware快捷方式设置,单击下一步继续安装.png

  • ⑧ 单击安装按钮:

VMware单击安装按钮.png

  • ⑨ VMware 输入许可证:

VMware单击许可证.png

VMware输入许可证.png

  • ⑩ 安装结束后,单击完成按钮:

VMware安装结束后,单击完成按钮.png

  • ⑪ 检查虚拟机软件是否安装了虚拟网卡:

查看VMware安装的虚拟网卡.png

查看VMware安装的虚拟网卡1.png

查看VMware安装的虚拟网卡2.png

2.3.2 配置网络

  • ① 打开 VMware 虚拟机软件:

image-20240116202917529

  • ② 编辑 → 虚拟网络编辑器:

image-20240116202955131

  • ③ Vmnet8 → 更改设置:

image-20240116203207282

  • ④ 更改子网 IP 地址为 :192.168.10.0 ,其目的是为了将 IP 固定。

image-20240116203357894

  • ⑤ DHCP 设置:

image-20240116203529749

image-20240116203627959

  • ⑤ 通过 cmd ,输入 ipconfig 命令,查看是否配置成功:

2.4 创建虚拟机

2.4.1 概述

  • 创建虚拟机,本质上就类似购买一台没有安装操作系统的裸机

2.4.2 创建虚拟机

  • ① 文件 → 新建虚拟机:

image-20240117090352182

  • ② 选择自定义类型的配置:

image-20240117090443216

  • ③ 虚拟机硬件兼容性:下一步即可。

image-20240117090529266

  • ④ 选择稍后安装操作系统

image-20240117090636337

  • ⑤ 选择虚拟机将安装的操作系统:

image-20240117090805295

  • ⑥ 设置虚拟机的名称安装位置

image-20240117090944676

WARNING

一个虚拟机一个安装目录(文件夹),防止引起文件的冲突。

  • ⑦ 虚拟机中处理器的配置:下一步即可。

image-20240117091051284

  • ⑧ 设置虚拟机的内存:至少 2048 MB以上。

image-20240117091202131

  • ⑨ 设置虚拟机的网络类型:下一步即可。

image-20240117091257738

  • ⑩ 设置 I/O 控制器类型:下一步即可。

image-20240117091402913

  • ⑪ 选择磁盘类型:下一步即可。

image-20240117091540264

  • ⑫ 选择磁盘:下一步即可。

image-20240117091640870

  • ⑬ 选择磁盘容量:调整为 40 GB。

image-20240117091832846

  • ⑭ 指定磁盘文件:下一步即可。

image-20240117091907233

  • ⑮ 创建虚拟机完毕:

image-20240117092013264

  • ⑯ 查看是否创建虚拟机成功:

image-20240117092101810

2.4.3 虚拟机归类(分类)

  • 实际情况下,我们可能会创建很多虚拟机,VMware 提供了文件夹的功能来管理虚拟机;其步骤如下所示:
  • ① 鼠标右键 → 创建文件夹:

image-20240117092324545

  • ② 修改文件夹的名称:

image-20240117092600931

image-20240117092643086

image-20240117092720769

  • ③ 将刚才创建的虚拟机到该文件夹下:

2.4.4 设置 CD/DVD

  • 以前,我们在一台裸机上安装操作系统的时候,需要通过 DVD 或 U 盘将操作系统的 ISO 镜像文件,安装到裸机上;
  • 同理,在使用虚拟机软件的时候,也需要此类步骤;其步骤如下:
  • ① 编辑虚拟机设置:

image-20240117093143947

  • ② 选择硬盘上的 ISO 镜像文件:

image-20240117093354461

  • ③ 查看是否配置成功:

image-20240117093435976

2.5 安装 Linux

  • 开启此虚拟机

image-20240117093516070

  • 鼠标点击进去之后,通过键盘上的方向键来选择:

image-20240117093610205

  • 注意⚠️:键盘上的方向键在这里

image-20240117093918602

  • ③ 设置操作系统的语言环境为中文

image-20240117094530342

  • ④ 设置系统安装目的地

  • ⑤ 设置软件选择:默认即可

  • ⑥ 设置 root 的密码:123456即可

WARNING

学习阶段无所谓设置什么密码,但是生产环境,必须复杂并且经常更换!!!

  • ⑦ 配置网络和主机名

image-20240224223931266

image-20240224224038036

image-20240224224138061

image-20240224224209724

image-20240224224245924

image-20240224224344051

  • ⑧ 查看配置网络和主机名是否成功:

image-20240224224420273

  • ⑨ 点击开始安装:漫长的等待……

  • ⑩ 安装完成之后,会提示重启系统,那就重启吧:

2.6 远程连接 Linux

2.6.1 查看 Linux 的 IP 地址

  • 通过 ifconfig 命令来查看 Linux 的 IP 地址:
shell
ifconfig

image-20240117101543732

2.6.2 远程连接 Linux

  • 可以通过 xshell 之类的远程连接工具来连接 Linux ,其步骤如下:
  • ① 新建会话:

image-20240117101749340

  • ② 输入 Linux 的 IP 地址:

image-20240117101906927

  • ③ 输入用户名和密码:

image-20240117102005340

  • ④ 接收和保存远程 Linux 的密钥:

image-20240117102123845

  • ⑤ 查看是否登录成功:

image-20240117102159684

Released under the MIT License.

+ \ No newline at end of file diff --git a/notes/about/index.html b/notes/about/index.html index fd9c8f5..b3c7fe7 100644 --- a/notes/about/index.html +++ b/notes/about/index.html @@ -22,8 +22,8 @@ -
Skip to content

后端技术栈

Spring  Spring Boot  MySQL  MariaDB  PostgreSQL  Oracle  Microsoft SQL Server  Redis  MongoDB  RabbitMQ  Solr  ElasticSearch  Logstash  Kibana  Kafka  Consul  Tomcat  JUnit5  Liquibase  Maven  Gradle  Spring Security  Hibernate  JSON  JWT  Java  Python  Android  Go  GraphQL 

前端技术栈

Vue3  TypeScript  Ant Design  Node.js  Vite  Webpack  NPM  Axios  ESLint  jQuery  BootStrap  ECharts  JavaScript  HTML5  CSS3  Tailwind CSS  Less 

DevOps

Git  GitHub  Gitee  gitlab  GitHub Actions  Jenkins  SonarQube  Docker  Harbor  Kubernetes  CentOS  Ubuntu 

运维技术栈

阿里云  Nginx  VMware  Prometheus  Grafana  Ansible  Lua 

测试技术栈

Postman  JMeter 

开发工具

Intellij IDEA  Eclipse  WebStorm  PyCharm  Android Studio  VSCode 

其他

Markdown  WordPress  GitHub Pages  Adobe Photoshop 

Released under the MIT License.

- +
Skip to content

后端技术栈

Spring  Spring Boot  MySQL  MariaDB  PostgreSQL  Oracle  Microsoft SQL Server  Redis  MongoDB  RabbitMQ  Solr  ElasticSearch  Logstash  Kibana  Kafka  Consul  Tomcat  JUnit5  Liquibase  Maven  Gradle  Spring Security  Hibernate  JSON  JWT  Java  Python  Android  Go  GraphQL 

前端技术栈

Vue3  TypeScript  Ant Design  Node.js  Vite  Webpack  NPM  Axios  ESLint  jQuery  BootStrap  ECharts  JavaScript  HTML5  CSS3  Tailwind CSS  Less 

DevOps

Git  GitHub  Gitee  gitlab  GitHub Actions  Jenkins  SonarQube  Docker  Harbor  Kubernetes  CentOS  Ubuntu 

运维技术栈

阿里云  Nginx  VMware  Prometheus  Grafana  Ansible  Lua 

测试技术栈

Postman  JMeter 

开发工具

Intellij IDEA  Eclipse  WebStorm  PyCharm  Android Studio  VSCode 

其他

Markdown  WordPress  GitHub Pages  Adobe Photoshop 

Released under the MIT License.

+ \ No newline at end of file diff --git a/notes/index.html b/notes/index.html index 4bf2c33..fb09faf 100644 --- a/notes/index.html +++ b/notes/index.html @@ -22,8 +22,8 @@ - - + + \ No newline at end of file