
视频元信息
- 视频标题:哈佛大学【中英⚡计算机科学导论(2026)|CS50x Introduction to Computer Science】 p02 P3 Lecture 1 - C
- 时长:约 2 小时(本片段为 Lecture 1 完整内容)
内容摘要(TL;DR)
本讲是 CS50x 第一周课程,主题为 C 语言。从 Scratch 图形化编程过渡到文本编程,介绍源代码与机器代码、编译器、VS Code 环境、C 语言基本语法(printf、变量、条件、循环、函数)、Linux 命令行操作,最后通过实际案例展示整数溢出和浮点精度等计算机局限性。核心思想:上周的概念完全不变,只是语法变了。
第一章:从 Scratch 到 C —— 思想不变,语法改变
1.1 开场:MIT 的“消防水管”比喻
[时间戳 82.1s] 课程开始,David 提到 MIT 的传统恶作剧——把饮水机接到消防栓上,旁边的标语写着:“在 MIT 接受教育就像试图从消防水管喝水”。计算机科学、编程、CS50 课程有时确实会让人有这种感觉——信息量巨大,像被高压水枪冲击。
理解:这个比喻是为了缓解初学者的焦虑。今天的内容看似吓人,但核心思想与上周完全一致,只是语法变了,看起来更吓人、更难记,但随着练习会形成肌肉记忆。
重点:不要关注你每天的感觉,而要关注三个月后你相对于上周(Week 0)的进步。
1.2 Week 0 回顾与 C 语言初印象
- 上周用 Scratch 实现的最简单程序:点击绿旗 → 小猫说“hello, world”
- 今天的 C 语言代码看起来像这样:
#include <stdio.h> int main(void) { printf("hello, world\n"); } - 颜色编码的对应关系:
- 黄色/橙色部分(Scratch 的“当绿旗被点击”)对应 C 语言中的
int main(void)—— 它本身不做事,但启动程序 - 紫色部分(Scratch 的“说”积木)对应
printf—— 真正干活的部分 - 白色文本对应
"hello, world\n"—— 要输出的内容
- 黄色/橙色部分(Scratch 的“当绿旗被点击”)对应 C 语言中的
思考:C 语言中很多“样板代码”暂时会被老师“挥手带过”,未来几周会逐步解释,现阶段不需要死记硬背每一行。
1.3 源代码 vs 机器代码
- 源代码(Source Code):程序员写的、人类经过训练能理解的代码(如 C 语言)
- 机器代码(Machine Code):计算机唯一理解的二进制——0 和 1
| 类型 | 谁能理解 | 例子 |
|---|---|---|
| 源代码 | 人类(经过训练) | printf("hello, world\n"); |
| 机器代码 | 计算机 | 01001000 01100101... |
- 编译器(Compiler):将源代码作为输入,产生机器代码作为输出的特殊软件。世界上有很多编译器,CS50 将使用最流行的一种。
第二章:开发环境 —— VS Code 与命令行
2.1 云端 VS Code
- 课程使用 Visual Studio Code(VS Code),业界非常流行的编辑器
- CS50 提供云端版本(cs50.dev),只需浏览器即可使用,所有工具预装预配置,避免技术麻烦
- 课程结束后可免费下载安装到自己的 Mac/PC,完全独立于 CS50
2.2 VS Code 界面组成
- 顶部右侧:代码标签页(类似浏览器标签)
- 底部右侧:终端窗口(Terminal Window)—— 运行编译和执行命令的地方
- 左侧:文件浏览器(显示文件与文件夹)
- 最左侧:活动栏(Activity Bar)—— 现代形式的菜单
理解:课程中老师会隐藏部分界面,让注意力集中在代码和命令上。
2.3 GUI 与 CLI
- GUI(Graphical User Interface):图形用户界面,有图标、按钮
- CLI(Command Line Interface):命令行界面,通过输入命令操作
- 软件世界基本分为 GUI 和 CLI 两类,有些软件两者兼有
趋势:程序员越来越多地使用键盘而非鼠标,因为键盘操作更快、更强大。虽然最初感觉像倒退,但最终会大幅提高生产力。
2.4 第一个 C 程序:hello.c
命令流程:
code hello.c—— VS Code 特定命令,创建新文件- 输入代码(
#include <stdio.h>、int main(void)、printf("hello, world\n");) make hello—— 编译源代码为机器代码,生成名为hello的可执行文件./hello—— 运行当前文件夹中的hello程序
命名约定:文件名全小写、无空格(如 hello.c 而非 Hello World.c),可避免很多麻烦。
理解:make hello 会自动寻找 hello.c 文件,这是编译器的一种“魔法”。
2.5 常见错误与调试
缺少分号
- 错误信息示例:
hello.c:5:29: error: expected ';' after expression - 包含文件名、行号、字符位置,非常有用
- 编译器不仅能转换代码,还能帮助找错
缺少头文件
- 错误信息:
error: call to undeclared library function 'printf' - 原因:
printf的定义在stdio.h头文件中 - 解决方案:在代码顶部添加
#include <stdio.h>
易错点:是
stdio.h(standard I/O),不是studio.h!这是非常常见的拼写错误。
2.6 头文件与库
- 头文件(Header Files):以
.h结尾,包含别人写好的代码,供你的程序使用 - 库(Library):别人写的、你可以复用的代码集合
- 例如:
printf来自标准 I/O 库;上周用到的 OpenAI 库也是类似概念
2.7 官方文档:Manual Pages
- C 语言传统文档称为 man pages,但往往晦涩难懂
- CS50 提供简化版:manual.cs50.io,用助教式的语言重写
- 可以查询
stdio.h中的函数,如printf - 也提供 CS50 自己的库文档(
cs50.h),包含get_string、get_int、get_char等函数
理解:这些“训练轮”函数(CS50 库)只在前几周使用,之后会摘掉。它们让初学者能轻松获取用户输入,而不用处理 C 语言中繁琐的细节。
第三章:从 Scratch 到 C —— 函数、变量与输入
3.1 printf 详解
Scratch 的“说”积木 → C 的 printf 函数:
printf中的f代表 formatted(格式化),比打印纯文本更强大- 括号对应 Scratch 的白色椭圆输入框
- 字符串必须用双引号包围
- 转义序列
\n:换行符,将光标移到下一行(纯粹为了美观,让提示符不跟输出挤在同一行) - 分号:C 语言中每条完整语句必须以分号结尾,类似英语的句号
易错点:C 语言对细节极其挑剔——引号、反斜杠、分号,任何一个搞错程序都会出错。初学者第一次编译失败非常正常,需要时间形成肌肉记忆。
3.2 常用转义序列
| 序列 | 含义 |
|---|---|
\n |
换行(光标垂直移动) |
\r |
回车(光标水平回到行首,类似老式打字机) |
\" |
打印双引号(避免歧义) |
\\ |
打印反斜杠 |
理解:编程语言大多是“基于行”的,一行内完成一个想法。如果想把光标移到下一行,不能用回车键把代码拆行,而要使用转义序列。
3.3 获取用户输入:get_string
Scratch 的“询问并等待”积木 → C 的 get_string 函数:
string answer = get_string("What's your name? ");
get_string是 CS50 库提供的函数,不是 C 标准库- 参数是提示用户的字符串
- 返回值存储在变量中,使用等号赋值
- C 要求声明变量类型:
string表示字符串类型 - 再次强调分号结尾
3.4 格式化输出:占位符
错误示范:
printf("hello, answer\n"); // 会原样打印 "hello, answer"
正确做法:使用占位符(placeholder) %s 表示字符串:
printf("hello, %s\n", answer);
- 第一个输入(引号内的内容)由程序员预先确定
- 第二个输入(
answer变量)来自用户,运行时才确定 - 逗号在引号内是英语标点,在引号外是 C 语法,用于分隔参数
重点:
%s是字符串占位符。当你写代码时不知道某个值,就先用占位符,运行时再传入变量。
3.5 常见问题
- 头文件从哪里来? 云端环境(cs50.dev)的服务器上预装了
cs50.h、stdio.h等文件,编译器知道去哪里找 - 为什么
\n不创建新行? 它确实创建新行,效果是把提示符推到下一行;不加\n时提示符会留在同一行 - 为什么提示用户时没有
\n? 这是程序员的选择——希望用户输入紧跟问号后面,光标停留在同一行等待输入 - 是否总是要写那四行样板? 今天先照做,下周会理解;但只有用到 CS50 库函数时才需要
#include <cs50.h>
第四章:Linux 与命令行基础
4.1 操作系统简介
- 世界上的操作系统:macOS、Windows、iOS、iPadOS、Android
- Linux:程序员、服务器、云端非常流行的操作系统,是 Unix 的后代
- Linux 性能极高,可支持成千上万用户,通常以 CLI 方式使用(无需图形界面,运行更快)
4.2 常用 Linux 命令
| 命令 | 功能 |
|---|---|
ls |
列出当前文件夹的文件 |
mkdir |
创建新文件夹(目录) |
rmdir |
删除目录 |
rm |
删除文件 |
mv |
移动/重命名文件 |
cp |
复制文件 |
cd |
更改目录(进入文件夹) |
rm删除文件时会询问确认,输入y确认mv的语法:mv 源 目标;如果目标是已存在的文件夹,则移动;如果目标是一个新文件名,则重命名cd ..表示进入父文件夹(上一级);.表示当前文件夹,..表示上一级- 输入
cd单独回车,可回到默认主目录(home directory)
理解:GUI 中能做的拖拽、新建文件夹等操作,在 CLI 中都有对应命令。命令行更高效,但需要记忆。CS50 的问题集会逐步指导命令用法,后期会默认你已掌握。
第五章:条件语句(Conditionals)
5.1 if 语句
Scratch 的 如果...那么 积木 → C 的 if:
if (x < y)
{
printf("x is less than y\n");
}
if后跟空格、括号(与函数无关,是 C 的条件语法)- 括号内是布尔表达式(Boolean expression),结果为真或假
- 花括号
{}拥抱多条语句,类似 Scratch 中橙色积木包裹紫色积木 - 缩进 4 个空格是 CS50 风格约定,让代码逻辑清晰
5.2 if-else 与 else if
if (x < y)
{
printf("x is less than y\n");
}
else
{
printf("x is not less than y\n");
}
多分支:
if (x < y)
{
printf("x is less than y\n");
}
else if (x > y)
{
printf("x is greater than y\n");
}
else
{
printf("x is equal to y\n");
}
重点:
==是相等比较,=是赋值! 人类几十年前决定用=表示把右边的值复制到左边的变量,结果在条件判断时只好用==表示相等。Scratch 为了不迷惑小孩用单等号,C 和大多数语言用双等号。
5.3 设计优化:不要问多余的问题
- 如果已经判断了
x < y和x > y,那么剩下的情况必然是x == y,无需再问第三个问题 - 错误示范:使用
else if (x == y)会浪费计算机和用户的时间 - 正确做法:用
else作为默认情况
理解:这是“设计(Design)”的体现——代码不仅要正确(Correctness),还要高效、清晰。
5.4 比较运算符
| 运算符 | 含义 |
|---|---|
< |
小于 |
> |
大于 |
<= |
小于等于(两个字符) |
>= |
大于等于 |
== |
相等 |
!= |
不等于(! 读作 “bang”,表示否定) |
思考:!= 实际上是 !(非)+ ==(相等)的缩写,为了省一个字符。
第六章:数据类型与变量
6.1 C 语言的基本数据类型
| 类型 | 含义 | 典型位数 |
|---|---|---|
bool |
布尔值(true/false) | 1 位(概念上) |
char |
单个字符 | 8 位 |
string |
字符串(来自 CS50 库) | 可变 |
float |
浮点数(有小数点的实数) | 32 位 |
double |
双精度浮点数(更精确) | 64 位 |
int |
整数(正负) | 32 位 |
long |
长整数(更大范围) | 64 位 |
- float vs double:float 用 32 位表示实数,但实数有无限多个,所以只能近似;double 用 64 位,更精确但仍是有限集合
- int 的范围:32 位可表示约 40 亿个值,但因为有正负,所以大约 -20 亿到 +20 亿
- long:64 位,范围大得多,但依然有限
6.2 从 CS50 库获取不同类型输入
get_string→ 字符串get_int→ 整数get_char→ 字符get_double→ 双精度浮点数get_float→ 浮点数- 没有
get_bool,因为获取真/假值通常不需要
6.3 格式化占位符汇总
| 占位符 | 类型 |
|---|---|
%s |
字符串 |
%c |
单个字符 |
%f |
浮点数 |
%i |
整数 |
%li |
长整数 |
理解:这些细节没有智力上的趣味,但是实用的、需要逐渐吸收的知识。
第七章:变量操作与算术
7.1 变量声明与赋值
Scratch 中创建计数器 → C 中:
int counter = 0; // 声明类型 + 变量名 + 赋值 + 分号
- 变量名可以任意起(如
answer、counter),约定全小写、无空格 - 必须指定类型
7.2 递增的多种写法
counter = counter + 1; // 标准写法:取出当前值,加 1,存回去
counter += 1; // 简写:加等于
counter++; // 最简写:自增 1
+=可以加任意数(counter += 2等)- 递减对应:
counter = counter - 1、counter -= 1、counter--
易错点:
counter = counter + 1不是数学等式,而是赋值——把右边的计算结果复制到左边变量。
7.3 示例程序:compare.c
#include <cs50.h>
#include <stdio.h>
int main(void)
{
int x = get_int("What's x? ");
int y = get_int("What's y? ");
if (x < y)
{
printf("x is less than y\n");
}
else if (x > y)
{
printf("x is greater than y\n");
}
else
{
printf("x is equal to y\n");
}
}
思考:ls 命令列出的文件中,带 * 后缀(如 compare*)表示该文件是可执行程序,不是普通文本文件。
7.4 流程图视角
- 代码可以画成流程图:菱形表示布尔判断,矩形表示操作
- 好的设计:判断 1 次、最多 2 次即可覆盖 3 种情况
- 坏的设计:无论什么情况都问 3 次问题,浪费时间
第八章:逻辑运算符与字符输入
8.1 示例程序:agree.c(同意条款)
#include <cs50.h>
#include <stdio.h>
int main(void)
{
char c = get_char("Do you agree? ");
if (c == 'y' || c == 'Y')
{
printf("Agreed.\n");
}
else
{
printf("Not agreed.\n");
}
}
- 单引号用于单个字符(
char),双引号用于字符串 get_char会强制用户输入单个字符,如果输入多个字符会反复重新提示- 大写
Y和小写y都需要支持
8.2 逻辑运算符
||(两个竖线)表示逻辑或(OR):两个条件中至少一个为真&&(两个与号)表示逻辑与(AND):两个条件都为真!表示逻辑非(NOT)
易错点:
c == 'y' && c == 'Y'是逻辑错误!一个变量不可能同时等于小写 y 和大写 Y,必须使用||。易错点:复制粘贴代码是坏设计。如果要修改重复的代码,需要改多处,容易遗漏。用逻辑运算符组合条件可以避免重复。
第九章:循环(Loops)
9.1 while 循环
Scratch 的“重复 3 次”积木 → C 的 while:
int i = 3;
while (i > 0)
{
printf("meow\n");
i--;
}
- 没有
repeat关键字,用while实现 - 计数器可以从 3 递减到 0,当
i > 0为假时循环停止 - 也可以从 0 递增到 3:
int i = 0;
while (i < 3)
{
printf("meow\n");
i++;
}
理解:从 0 开始计数是编程惯例,因为这样循环条件 i < 3 能直观地看到起始点和结束点。
9.2 for 循环
for (int i = 0; i < 3; i++)
{
printf("meow\n");
}
- 语法:
for (初始化; 条件; 更新) - 把初始化、条件检查、递增都放在一行,更紧凑
- 与 while 循环完全等价,是更常见的惯例
9.3 无限循环
while (true)
{
printf("meow\n");
}
- 没有
forever积木,用while (true)实现无限循环 - 条件永远为真,循环永不停止,除非用
break跳出
提醒:无限循环会持续占用 CPU,导致 VS Code 报警("high CPU utilization detected")。中断方法:按
Ctrl + C。
9.4 do-while 循环
int n;
do
{
n = get_int("What's n? ");
}
while (n < 0);
- 条件在底部检查,而不是顶部
- 适合“至少执行一次”的场景(比如至少要问用户一次输入)
- 对比:普通 while 先检查条件再执行;do-while 先执行再检查条件
理解:这就像《乐一通》里的角色——跑路者(Road Runner)会在悬崖边检查条件,而土狼(Wile E. Coyote)会先跑出去,然后才意识到脚下是悬崖。
9.5 用户输入验证(错误示范 vs 正确示范)
错误示范(重复代码):
int n = get_int("What's n? ");
if (n < 0)
{
n = get_int("What's n? ");
}
if (n < 0)
{
n = get_int("What's n? ");
}
// 无限重复...
正确示范(使用 while true + break):
while (true)
{
n = get_int("What's n? ");
if (n >= 0)
{
break;
}
}
更简洁(do-while):
int n;
do
{
n = get_int("What's n? ");
}
while (n < 0);
9.6 作用域(Scope)问题
重点:在循环内部声明的变量,其作用域仅限于该循环的花括号内。循环结束后变量不存在(undeclared identifier)。
// 错误:n 在 while 内部声明,循环外无法使用
while (true)
{
int n = get_int("What's n? ");
if (n >= 0) break;
}
printf("%i\n", n); // 错误:n 未声明
// 正确:在循环外声明
int n;
do
{
n = get_int("What's n? ");
}
while (n < 0);
第十章:自定义函数与抽象
10.1 创建无参数无返回值函数
Scratch 中自定义“meow”积木 → C 中:
void meow(void)
{
printf("meow\n");
}
- 第一个
void:函数不返回任何值 - 第二个
void:函数不接受任何参数(输入) - 函数名后必须有括号,函数体用花括号
10.2 创建带参数的函数
void meow(int n)
{
for (int i = 0; i < n; i++)
{
printf("meow\n");
}
}
- 参数需要声明类型和名称(如
int n) - 调用时传入具体值:
meow(3);
10.3 原型(Prototype)
易错点:C 编译器从上到下读取文件。如果函数定义在
main之后,main中调用该函数会报错(undeclared identifier)。
解决方案:在文件顶部(main 之前)添加函数原型——只复制函数的第一行(签名)并以分号结尾:
void meow(int n); // 原型:向编译器承诺这个函数稍后会定义
int main(void)
{
meow(3);
}
void meow(int n)
{
for (int i = 0; i < n; i++)
{
printf("meow\n");
}
}
理解:原型是“对编译器的承诺”,告诉编译器“别担心,这个函数后面会存在”。这是少数允许复制粘贴代码的场景。
10.4 注释
// 这是注释:以两个斜杠开头,给人看,不给计算机看
- 注释是给自己的便利贴,提醒自己或他人代码的作用
- 好的注释能提高代码的“风格(Style)”评分
10.5 返回值的函数
int get_n(void)
{
int n;
do
{
n = get_int("What's n? ");
}
while (n < 0);
return n;
}
return n;把值返回给调用者- 函数类型从
void改为int,表示返回整数 - 这样可以把“获取非负整数”这个逻辑抽象成一个可复用的函数
理解:这就是“抽象(Abstraction)”的力量——把解决过的问题打包成函数,以后直接调用,不用重复思考细节。
第十一章:代码质量三维度 —— 正确性、设计、风格
11.1 三个评价维度
| 维度 | 含义 |
|---|---|
| 正确性(Correctness) | 代码是否按要求工作 |
| 设计(Design) | 代码是否高效、合理、不浪费资源 |
| 风格(Style) | 代码是否美观、缩进、命名清晰 |
- 正确:逻辑正确,但可能问多余的问题(浪费 CPU 和用户时间)
- 设计:像写议论文,不仅正确还要论证有力
- 风格:缩进一致、变量名有意义(如
row、column而非i、j随意)
11.2 CS50 的辅助工具
- check50:自动测试代码正确性(输入特定 slug 标识符)
- style50:检查代码风格,左侧显示你的代码,右侧显示应该的样子
- design50:基于 CS50 Duck(AI)给出设计改进建议,类似 ChatGPT
思考:真实公司中会有官方风格指南或工具,让所有人的代码看起来一致,即使每个人解决问题的方案不同。
第十二章:综合案例 —— 文本版超级马里奥
12.1 打印一行问号
#include <stdio.h>
int main(void)
{
printf("????\n");
}
用循环改进:
for (int i = 0; i < 4; i++)
{
printf("?");
}
printf("\n");
易错点:如果
printf("?\n")放在循环内,会输出一列问号而不是一行。换行符应该在循环结束后单独打印。
12.2 打印一列砖块
for (int i = 0; i < 3; i++)
{
printf("#\n");
}
12.3 打印 3×3 网格(嵌套循环)
int main(void)
{
for (int row = 0; row < 3; row++)
{
for (int column = 0; column < 3; column++)
{
printf("#");
}
printf("\n");
}
}
- 外层循环处理行,内层循环处理列
- 内层循环结束后打印换行,开始下一行
- 变量名用
row、column比i、j更清晰
理解:这就像老式打字机——打印一行,回车,再打印下一行。
12.4 常量(const)
const int n = 3;
const告诉编译器这个变量的值永远不能改变- 防止自己或同事意外修改
- 比硬编码数字更好:只需改一处,所有地方都更新
易错点:硬编码(如数字 3 出现多次)是坏设计。如果改需求,需要改多处,容易遗漏。用变量或常量统一管理。
第十三章:计算机的局限性 —— 整数溢出与浮点精度
13.1 示例:计算器 calculator.c
#include <cs50.h>
#include <stdio.h>
int main(void)
{
int x = get_int("What's x? ");
int y = get_int("What's y? ");
printf("%i\n", x + y);
}
- 可以直接在
printf中做加法,不一定需要中间变量 - 使用 Tab 键自动补全文件名,上下箭头浏览命令历史
13.2 整数溢出(Integer Overflow)
- 演示:不断“翻倍并传给下一个人”(类似 meme 的指数增长游戏)
- 当数值超过 int 能表示的最大值(约 20 亿)时,溢出发生:
- 先变成负数(因为符号位被翻转)
- 最终归零
- 原因:计算机为每个整数分配固定数量的比特(通常 32 位或 64 位),能表示的数值范围有限
考点:整数溢出——试图存储一个超出类型范围的值,导致回绕(wrap around)。
理解:就像 3 位二进制只能表示 0~7,想表示 8 就需要第 4 位;如果没有第 4 位,8 就变成了 0。
13.3 真实案例:波音 787
- 波音 787 连续通电 248 天后,发电机控制单元(GCU)的软件计数器溢出,导致飞机失去全部交流电力
- 计数器以十分之一秒为单位,32 位整数在 248 天后溢出
- 短期解决方案:重启飞机(关闭再打开,变量重置)
- 长期解决方案:软件升级
思考:这就是为什么“重启”能解决很多电子设备问题——所有变量回到默认值。
13.4 吃豆人(Pac-Man)256 关 bug
- 游戏最高可玩到第 255 关,但因为缺少检查关卡的条件,第 256 关会溢出整数,屏幕出现乱码
- 能打到第 256 关被视为一种荣誉徽章
13.5 截断(Truncation)
int x = 1;
int y = 3;
printf("%i\n", x / y); // 输出 0,而不是 0.333...
- 整数除以整数,结果仍是整数,小数部分被截断(丢弃)
- 解决方案:使用
float或double类型,并用%f占位符
易错点:整数除法会直接舍弃小数部分,不是四舍五入。
13.6 浮点不精确(Floating-point Imprecision)
float x = 1;
float y = 3;
printf("%.50f\n", x / y); // 显示 50 位小数
- 输出:
0.33333333333333331482961625624739099293947219848633... - 后面出现随机数字,因为 32 位浮点数无法精确表示无限小数
- 用
double(64 位)可以更精确,但依然无法完全精确
理解:实数有无限多个,但比特是有限的,所以计算机只能存储近似值。这是“浮点不精确”问题。
13.7 Y2K 问题与 2038 年问题
- Y2K(2000 年问题):早期计算机用 2 位数字表示年份,1999→2000 时可能混淆为 1900。全球紧急修复,世界没有毁灭。
- 2038 年问题:自 1970 年 1 月 1 日起,计算机用 32 位整数计算秒数。到 2038 年 1 月 19 日,计数器溢出,系统可能认为日期是 1901 年 12 月 13 日。
提醒:2038 年问题尚未解决,需要新一代程序员(也就是你们)在 2038 年前修复。
第十四章:本讲总结与展望
- 本周所有概念与上周(Scratch)一一对应:函数、变量、参数、返回值、条件、循环
- 语法变了,但思想完全一样
- 下周将深入解释
main函数、头文件、编译器内部机制 - 问题集 1(Problem Set 1)即将发布
学习建议:
- 不需要逐行抄写课堂代码,课程网站有所有示例
- 遇到问题先查官方文档(manual.cs50.io)
- 可以使用 AI 工具(如 cs50.ai)但应养成查文档的习惯
- 练习形成肌肉记忆,细节错误会随实践减少
关键标签/关键词
CS50 C语言 编程入门 源代码 机器代码 编译器 VS Code 命令行 Linux printf 变量 数据类型 条件语句 循环 函数 作用域 原型 抽象 整数溢出 浮点不精确 Y2K 2038问题 正确性 设计 风格
生成时间:2026-09-02 15:53:49 生成平台:VideoNote