1. 输入输出初步认识
文件的读写,标准上称之为输入流(input stream)和输出流(output stream)。
输入流的数据会首先被暂存到一个叫缓冲区(buffer)的内存区域。
缓冲区的作用:
- 检查安全的一种机制;
- 一部分数据打包放在缓冲区中,用于批量处理,提高数据处理的效率。
标准输入(stdin):指从键盘输入数据到操作系统中,存储这些数据在标准输入关联的缓冲区中,等待被程序读取。
标准输出(stdout):可以把数据发送到外部,例如输出数据到控制台、文件等。
“保持热爱,奔赴星海”
文件的读写,标准上称之为输入流(input stream)和输出流(output stream)。
输入流的数据会首先被暂存到一个叫缓冲区(buffer)的内存区域。
缓冲区的作用:
标准输入(stdin):指从键盘输入数据到操作系统中,存储这些数据在标准输入关联的缓冲区中,等待被程序读取。
标准输出(stdout):可以把数据发送到外部,例如输出数据到控制台、文件等。
正常情况下,在官网下载Visual Studio时,会下载一个Visual Studio Installer,在软件中可以选择想要下载的VS版本并管理组件和更新。
但Visual Studio Installer中一般只有当前的最新版本,例如目前只有VS 2026可以下载,此时如果有一些特殊需求,想要下载以前版本的Visual Studio,就比较麻烦了,官网很难找到对应的安装包。
本文提供了一种通过官方渠道一键下载旧版本VS的方法,希望可以帮到你。
C语言中字符串的处理是非常重要的。
可以使用char直接定义一个单个字符,使用单引号('')初始化,用%c可以将单个字符输出:
1 | char c = 't'; |
字符串本质上来说是一个由字符组成的数组,类型是char[],字符串可以储存由多个字符组成的字符序列,用大括号加双引号({""})或直接用双引号("")初始化,用%s可以将字符串输出,直接传入数组名即可:
1 | char str[] = "Hello"; // 实际的字符数组:{'H', 'e', 'l', 'l', 'o', '\0'} |
C语言中,字符串的结尾必定是\0,如果结尾丢失\0,会导致意料之外的问题。
1 | char str1[6] = "Hello"; // 正确,数组长度足以存储字符串和终止符 |
因此定义字符串时一般不会显式指定字符数组的长度,应该使用和数组类似的特性,直接让编译器自行计算长度,这样可以防止手动计算出错。
微软在处理字符串问题时,推荐使用带_s后缀的函数,例如对于字符串读取,微软推荐使用scanf_s而不是scanf,这种新的函数对字符串有特殊处理,可以避免出现字符串的未定义行为。
字符串也可以使用指针定义,与数组的指针类似,字符串的指针可以理解为指向字符数组中第一个字符的指针。
指针定义的字符串同样可以使用%s输出,但输出时与其他类型的指针不同,不需要有解引用符(*),直接将指针传入即可。
1 | char* ptr_str = "Hello!"; // 指向字符串常量的指针 |
需要注意的是,使用指针定义的字符串,其指针指向的是字符串常量,因此不可以修改单个字符,强制修改会导致未定义行为,且编译器不会显式报错,非常危险。
1 | ptr_str[0] = 'h'; // 未定义行为,字符串常量不可修改,可能会导致程序崩溃 |
想要修改指针定义的字符串时,只能直接修改指针,使其直接指向另一个字符串常量:
1 | ptr_str = "world!"; // 指针可以指向另一个字符串常量 |
一般情况下,字符串定义后不会再进行修改,因此字符串会定义为const常量字符数组类型,或者在定义指针字符串的时候显式写上const关键字。
1 | const char str[] = "Hello"; |
这样定义的话,修改字符串中的某个字符时,编译器会显式报错,更为安全。
如果不加
const常量类型,使用字符数组定义的字符串可以直接单独修改其中的字符。
1 str[0] = 'h';此外,如果定义字符指针指向定义好的指针数组,通过指针可以实现字符的修改,这个与其他类型的数组类似。
1
2
3 char str[] = "Hello";
char* ptr_str = str;
ptr_str[0] = 'h'; // 修改指针指向的内容同样也可以使用这个特性结合指针加法遍历字符串数组:
1
2
3
4
5
6
7 char str[] = "Hello";
char* ptr_str = str;
while (*ptr_str != '\0'){
printf("%c\n", *ptr_str);
ptr_str++;
}
因此,如果想要定义一个需要修改的字符串,应该使用字符数组来定义,要么隐式定义,要么定义的数组长度应满足最大长度要求。
当字符数组的长度大于有效值时,字符串的结尾以及其他无效字符均为\0。
如果想要定义一个不需要修改的字符串,可以使用const指针定义,也可以定义为const常量类型的字符数组,在修改时会有明显的报错,可读性更强。
结构体(Structures)是一种用户可以自定义的类型,用来储存结构化的数据并实现一些功能。
结构体定义时必须以struct开头,后面是自定义的结构体名,大括号内部是这个结构体所包含的成员,这些成员可以是常见的任意基本数据类型,各个成员之间用;隔开。
例如一个日期的结构体定义:
1 | struct Date { |
这个结构体中包含了三个成员,可以将年份、月份、天数统一结构化地存储在这个结构体中,方便管理和使用。
结构体和其他数据类型一样,定义好后可以初始化使用,可以在初始化时指定每种成员变量的初始值。
结构体初始化同样需要以struct开头,后面是想要初始化的结构体名,然后写任意自定义的初始化结构体名称。初始化的各个成员之间用,隔开。
例如日期结构体的初始化:
1 | struct Date today = { 2026, 1, 1 }; |
初始化值的各个成员需要与定义时的成员一一对应。
需要注意的是,只有初始化结构体的时候才可以整体赋值,在非初始化时只能逐个成员赋值,不能整体赋值。
1
2
3
4
5 struct Date today = { 2026, 1, 1 }; // 正确:定义时初始化
struct Date today;
//today = { 2026, 1, 1 }; // 错误:不能这样赋值
today = (struct Date){ 2026, 1, 1 }; // 正确:使用复合字面值赋值
计算机中的地址(address)一般指代内存中的某一个存储单元的地址,可以简单理解为某一个内存存储单元的编号。
**地址是内存中存储数据的位置的唯一标识。**对于储存在内存中的变量,只要得知这个变量的地址,即可非常快速地拿到它的值,并对其进行修改等操作。
指向内存中的某一块地址的一个特殊的变量叫做指针。
function的中文翻译一般为函数,但代码中的函数与数学中的函数不同,数学中的函数强调映射,而代码中的函数其实是一个功能块。因此function的比较准确的翻译应该是类似于Java中的“方法”。
函数的功能在于,当许多处代码中都会用到相同的功能时,可以将功能块提取出来,打包成一个函数,这样只需要在合适的时候调用函数即可。
因此可以总结一下,函数的作用就是模块化地将一些功能抽离打包出来,在其他地方复用。
Git Flow是一种标准Git分支模型,由Vincent Driessen于2010年提出,他开发的插件git-flow可以自动化完成分支的创建、合并等工作,大大减轻了分支操作的工作量。在十几年前Git刚刚出现的时候是有意义的,当时SVN比较普及,人们不太懂如何使用Git。
但在十几年后的今天,由于Git Flow的结构过于繁琐和复杂,它完全放弃了rebase,分支结构错综复杂,即使有插件git-flow,但使用和维护起来的工作量仍然不小,不利于现如今的持续交付流程。
我们需要一种新的Git分支模型来适应现代化的开发需求,本文推荐由Fork的开发者提出的Lean Branching:⭐️ Lean Branching - a git branching model to keep clean history · Issue #1432 · fork-dev/TrackerWin
Git Flow是一种标准Git分支模型,阅读本文前,建议先阅读文章“标准Git分支模型介绍(配合Fork实操) | 青江的个人站”以了解Git Flow的基本流程。
可以看到,Git Flow流程中有着大量的新建、提交、合并分支的操作,导致整个过程非常繁琐,加大了开发的工作量。
因此,Git Flow的创造者Vincent Driessen开发了git-flow插件(nvie/gitflow: Git extensions to provide high-level repository operations for Vincent Driessen’s branching model.),可以通过一行命令来自动化地创建或完成支持分支,从而简化操作。
此外,Fork支持git-flow,可以在图形界面中完成整个流程。
本文将配合Fork对git-flow插件的使用做基础的介绍。
本文参考文章:A successful Git branching model » nvie.com,作者是Vincent Driessen
本文在原文的基础上做了本地化以及一部分现代化改动,例如将文章中的主分支名
master改为现在更为常用的main等,同时配合Fork做一些实操介绍。
阅读本文前,建议先阅读文章“【保姆级教程】Git客户端Fork的基础使用 | 青江的个人站”以了解Git与Fork的基础用法。
使用标准Git分支模型的核心作用是为代码的集成、测试和发布建立清晰可控的工作流程,避免非标准分支导致的开发混乱、出现问题时难以排查或回溯的情况。
通过定义如长期稳定的main主干分支、临时性的功能开发分支(feature)、预发布测试分支(release)以及线上问题紧急修复分支(hotfix)等角色,该模型将不同开发阶段和目的的工作有效隔离,避免相互干扰;这使得团队成员能够安全地并行推进多个任务,同时始终保证主干分支的代码处于可随时发布的稳定状态,从而显著降低集成冲突风险、提升软件交付质量与效率,并为版本追踪、问题排查及协作沟通提供了结构化的历史记录基础,最终实现开发过程的有序性和可靠性。
下面是一个完整的标准Git分支模型示意图:
