视频封面

视频元信息

  • 视频标题:哈佛大学【中英⚡计算机科学导论(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" —— 要输出的内容

思考: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

命令流程:

  1. code hello.c —— VS Code 特定命令,创建新文件
  2. 输入代码(#include <stdio.h>、int main(void)、printf("hello, world\n");)
  3. make hello —— 编译源代码为机器代码,生成名为 hello 的可执行文件
  4. ./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