☰
C语言初学者破冰指南:从Hello World到编译报错全解析
2026/11/3 23:44:55 网站建设 项目流程

1. 这不是教材搬运,而是一份给真实初学者的“C语言破冰地图”

你打开《明解C语言 第三版 入门篇》,翻到第一章——“初识C语言”,页面上印着“Hello, World!”、#include <stdio.h>、int main()这些符号,但心里可能正盘算着:这串字符到底在跟电脑说什么?为什么非得写return 0;?printf里的双引号和分号,少一个就报错,它们到底管什么用?别急,这不是你一个人的困惑。我带过几十期零基础编程训练营,几乎每届都有学员卡在这一章,不是因为智力不够,而是因为教材默认你已经站在了“理解编译器如何思考”的起点上——可现实是,绝大多数人连“编译器”长什么样都没见过。

这本书的标题里有个关键词叫“明解”,但真正的“明”,不在于把概念讲得多漂亮,而在于把初学者脑中那团混沌的疑问,一根一根抽出来、捋直、打结、再系到实际操作上。所以这篇整理,完全跳过“本章小结”“课后习题答案”这类教辅套路,直接从你合上书后最可能做的第一件事开始:在自己电脑上敲出能跑起来的代码,并且真正看懂每一行在干什么、为什么必须这么写、改哪里会出什么问题。它不追求覆盖全书所有例题,但确保你亲手敲完这章全部核心示例后,能独立解释:为什么main函数必须有返回值?为什么printf要加头文件?为什么//后面的内容电脑会自动忽略?这些看似琐碎的问题,恰恰是后续学指针、内存管理、多文件编译时所有“灵光一现”或“百思不解”的底层支点。适合谁?适合刚装好Code::Blocks却对着黑窗口发呆的高中生;适合转行想学嵌入式、但被gcc报错信息吓退的硬件工程师;也适合想给孩子讲清“程序到底怎么运行”的家长——只要你愿意花30分钟,跟着命令行一步步敲、改、试、错,这篇就是为你写的。

2. 内容整体设计与思路拆解:为什么从“黑窗口”和“报错信息”切入?

2.1 不按教材顺序,先建“执行感”,再补“理论感”

《明解C语言》第一章的逻辑是:定义→语法→示例→总结。这是知识传递的线性路径,但对初学者而言,它缺失了最关键的“反馈环”。你照着抄完printf("Hello, World!\n");,按下F9,屏幕一闪而过,或者弹出一堆红色文字——这时你大脑里第一个念头绝不是“哦,我掌握了输出语句”,而是“我是不是又打错了?它到底想让我改哪?” 如果不立刻解决这个焦虑,后续所有关于“变量”“数据类型”的讲解,都会变成悬浮在空中的概念。

因此,我的整理彻底重构了学习动线:
第一步,强制你看到“程序运行”的物理过程——不是IDE里一个按钮,而是命令行下gcc hello.c -o hello && ./hello这一串字符如何被系统逐字解析、调用编译器、生成可执行文件、最终由操作系统加载运行。你必须亲手输入、观察、记录每一次回车后的屏幕变化。
第二步,把教材里轻描淡写的“错误提示”变成你的第一课老师——error: expected ';' before '}' token这类报错,教材通常只说“检查分号”,但没告诉你:为什么编译器会在这里报错?它是在扫描到}时才发现前面缺分号,还是在读取整行时就已标记异常?我们通过故意删掉分号、多加括号、写错函数名,制造5种典型错误,然后对照GCC的报错定位(第几行第几列)、错误类型(error vs warning)、错误描述(token、syntax、undefined reference),建立“错误-原因-修复”的肌肉记忆。
第三步,才回到教材正文,用你刚刚亲手验证过的现象,反向解读概念。比如教材说“#include <stdio.h>用于包含标准输入输出库”,你此刻就能立刻联想到:没有它,printf就会报undefined reference to 'printf'——原来这句话不是空话,而是告诉编译器:“去哪个文件里找printf这个功能的实现代码”。

这种设计,本质是把“被动接收定义”切换为“主动构建认知锚点”。每一个你亲手触发的错误、每一次你手动修复的成功,都比十遍教材原文更牢固地钉在你的神经回路上。

2.2 工具链选择:为什么坚持用命令行+GCC,而不是纯图形IDE?

书中推荐使用Code::Blocks或Visual Studio,这没错——它们对新手友好。但第一章的深层目标,是让你建立对“C语言程序生命周期”的直觉:源代码(.c)→ 预处理(展开头文件)→ 编译(生成汇编)→ 汇编(生成目标文件.o)→ 链接(合并库函数,生成可执行文件)。图形IDE把这些步骤封装成一个“构建”按钮,你点一下,它就默默完成了所有事。这很高效,但代价是:你永远不知道#include到底干了什么,main函数的返回值如何被操作系统捕获,甚至printf这个看似简单的函数,背后调用了多少系统级API。

所以我坚持要求你打开终端(Windows用CMD/PowerShell,macOS/Linux用Terminal),手动输入GCC命令。这不是为了复古,而是为了“可见性”。举个具体例子:当你执行

gcc -E hello.c -o hello.i

你会得到一个hello.i文件,里面全是展开后的代码——原本一行#include <stdio.h>,变成了上千行声明和宏定义。你滚动鼠标,亲眼看到printf的函数原型藏在哪一行,stdin/stdout这些常量是如何被定义的。这种“掀开盖子看引擎”的体验,是任何IDE的“跳转到定义”功能都无法替代的。它让你明白:C语言不是魔法,它是一套极其严谨、层层递进的机械流程,而你,是那个亲手拧紧每一颗螺丝的人。

当然,这不是否定IDE的价值。后续学调试、项目管理时,IDE是不可替代的。但第一章,必须用最原始的方式,把“程序如何从文本变成动作”这个黑箱,彻底打开给你看。

2.3 示例精简逻辑:为什么只聚焦4个核心示例,而非全章罗列?

原书第一章包含约12个代码示例,从最简Hello, World!到带变量计算的sum.c。我的整理只保留并深度拆解以下4个:

  1. hello.c:最简输出,用于建立“编译-运行”闭环;
  2. hello2.c:加入换行符\n和制表符\t,用于理解转义字符的物理效果;
  3. calc.c:含两个整数相加并输出,引入变量声明、赋值、scanf输入;
  4. error_demo.c:一个故意写满5种错误的“反面教材”,专用于错误分析训练。

理由很实在:初学者的认知带宽极其有限。同时面对“输出格式控制符%d”、“输入缓冲区”、“变量作用域”、“ASCII码表”等七八个新概念,大脑会直接过载,最后记住的只有“好难”。这4个示例,恰好构成一条最小可行能力链:

  • 能输出固定文本 → 能控制输出位置(换行/缩进) → 能接收用户输入并参与计算 → 能读懂并修复自己的错误。
    每一步都只增加一个新变量,且前一步的成果是后一步的基石。比如calc.c里scanf("%d", &a);这行,如果你没亲手试过hello2.c里\n的效果,就无法理解为什么输入后要按回车——因为scanf默认以换行符作为输入结束标志。这种环环相扣的依赖关系,只有通过精简示例、深挖细节才能暴露出来。

3. 核心细节解析与实操要点:从“抄代码”到“懂代码”的7个关键断点

3.1 断点一:#include <stdio.h>——它不是装饰,而是“借工具”的契约

很多初学者以为#include只是告诉编译器“我要用printf”,其实远不止。它本质是一次预处理指令,发生在编译之前。当你写:

#include <stdio.h>

预处理器会做一件事:把stdio.h这个文件的全部内容,原封不动地复制粘贴到当前.c文件的这一行位置。你可以用GCC的-E参数亲眼验证:

gcc -E hello.c | head -n 20

你会看到开头几百行全是stdio.h里的宏定义、函数声明,比如:

extern int printf (const char *__restrict __format, ...);

这就是printf的“合同”——它声明了printf是一个接受字符串和可变参数的函数,返回整数。没有这个声明,编译器在遇到printf("Hello");时,会懵:“printf是什么?变量?函数?我该分配多少内存?参数怎么传?”

提示:<stdio.h>里的h代表“header file”(头文件),它不包含printf的实际代码(那是libc.a静态库或libc.so动态库里的事),只提供“接口说明”。就像你去修车,师傅先给你看维修手册(头文件),告诉你发动机有几个螺丝(函数参数),怎么拧(调用方式),但手册本身不会让车跑起来。

实操心得:下次编译报错undefined reference to 'printf',90%是因为忘了#include <stdio.h>,或者手误写成了#include <studio.h>(少了个i)。别急着搜解决方案,先用gcc -E看看预处理后的文件里有没有printf的声明行——这是最直接的诊断法。

3.2 断点二:int main()——为什么必须是int?为什么必须有return 0;?

教材说“main函数是程序入口”,但没说清楚:谁在调用它?调用完后它要把什么还回去?真相是:main函数不是被“上帝”调用的,而是被操作系统调用的。当你双击./hello,操作系统加载这个可执行文件,找到main函数的地址,然后跳过去执行。执行完后,操作系统需要知道:“这个程序是成功跑完了,还是中途崩溃了?” 这就是return值的意义。

int main()中的int,声明了main函数的返回值类型是整数。而return 0;,是向操作系统报告:“一切正常,退出码为0”。非零值(如return 1;)则表示异常。你可以亲自验证:

./hello echo $?

如果hello.c里写了return 0;,第二行会输出0;如果改成return 42;,就输出42。这个$?就是上一个命令的退出状态,Linux脚本里常用它做条件判断。

注意:C99标准规定,如果main函数末尾没有return语句,编译器会自动补上return 0;。所以你删掉return 0;,程序依然能跑,但这是编译器的“好心帮忙”,不是规范写法。养成显式写return 0;的习惯,等于在代码里埋下一句注释:“我确认程序正常结束”。

常见误区:有人写void main(),认为“我不需要返回值”。这是严重错误。void main()在某些旧编译器(如Turbo C)里能通过,但在GCC、Clang等现代编译器中,它会导致未定义行为(Undefined Behavior),程序可能看似正常,也可能在不同环境下崩溃。记住:int main()是唯一符合C标准的写法。

3.3 断点三:printf里的双引号、分号、\n——标点符号的物理意义

初学者常把printf("Hello, World!\n");当成一个不可分割的整体。其实每个符号都在执行明确的物理任务:

  • 双引号":界定字符串字面量(string literal)的边界。编译器看到",就知道接下来的字符不是代码,而是要原样输出的数据。如果漏掉一个",编译器会一路扫描到文件末尾,报错expected 'EOF'(期待文件结束),因为它以为字符串还没结束。
  • 分号;:C语言的语句终结符。它告诉编译器:“这一行指令到此为止,可以开始解析下一行了”。没有它,printf("Hello"); int a = 5;会被当成同一行,语法直接错误。
  • \n:换行符(newline character),一个单字符,不是\加n两个字符。它的ASCII码是10,作用是让光标跳到下一行开头。你可以在代码里写printf("Line1\nLine2");,输出就是:
Line1 Line2

而不是Line1\nLine2。

实操技巧:想看清\n的真实效果,可以用od -c命令查看输出的ASCII码:

./hello | od -c

如果hello.c里有\n,你会看到012(八进制10);如果没有,就只有字母和空格的ASCII码。这是调试输出格式问题的终极手段——当你的程序输出乱成一团,别猜,直接od -c看原始字节。

3.4 断点四:scanf的&符号——为什么变量名前要加“取地址符”?

scanf("%d", &a);这行是初学者最大陷阱。很多人记成“scanf后面都要加&”,结果在printf里也写printf("%d", &a);,输出一串莫名其妙的大数字。真相是:scanf需要知道“把用户输入的数字,存到内存的哪个位置”。而a本身是变量的值(比如a=5),&a才是变量a在内存中的地址(比如0x7fff5fbff6ac)。

打个比方:a是你家的门牌号“幸福路123号”,&a是快递员需要的精确GPS坐标。scanf是快递员,它必须拿到坐标(&a),才能把包裹(用户输入的数字)准确送到你家(变量a的内存位置)。而printf是邮局公告员,它只需要知道“幸福路123号”这个地址对应什么信息(a的值),不需要GPS坐标。

提示:&只用于scanf这类“需要修改变量值”的函数。printf、sqrt、strlen等只读取值的函数,一律传变量名本身(a,str),不加&。

常见错误排查:如果scanf后printf输出总是0或乱码,90%是忘了&。用printf("a=%d, &a=%p\n", a, &a);打印出来对比,立刻能发现&a是否被正确传入。

3.5 断点五://注释——为什么它能让代码“隐身”,但不能跨行?

//是C99引入的单行注释,从//开始到本行结束的所有字符,编译器完全忽略。它的物理机制很简单:预处理器在扫描源码时,一旦遇到//,就直接跳过后续所有字符,直到遇到换行符\n,然后继续扫描下一行。

这意味着:

  • //不能跨行。写// 这是一段很长的\n注释,第二行注释会被当作普通代码,大概率报错。
  • //可以出现在一行的任何位置。int a = 5; // 初始化a完全合法。
  • //内部不能嵌套/* */,反之亦然。// /* 这不会被忽略 */,因为//已生效,/*只是普通字符。

实操心得:注释不是可有可无的装饰。它是你和三个月后的自己对话的渠道。我在calc.c里强制要求每行关键代码后加注释,例如:

scanf("%d", &a); // 等待用户输入一个整数,存入变量a的内存地址

这样,当你某天回来看代码,不用重新推演逻辑,一眼就懂。而且,注释写得越细,你对代码的理解就越深——因为你要用自然语言描述机器行为,这本身就是一次认知校准。

3.6 断点六:编译器报错信息的“三要素”解码法

GCC的报错信息格式固定:文件名:行号:列号: 错误类型: 描述。例如:

hello.c:5:1: error: expected ';' before '}' token

这行信息包含三个关键解码点:

  1. 定位:hello.c:5:1—— 错误发生在hello.c文件第5行第1列。注意:列号1通常是行首,所以错误很可能在第4行末尾(比如少了个分号)。
  2. 类型:error(致命错误,编译终止) vswarning(警告,编译继续,但可能有隐患)。初学者务必先消灭所有error,warning留到后期优化。
  3. 描述:expected ';' before '}' token—— “在}这个符号之前,期望看到分号”。这里的token(记号)是编译器对代码的最小单位切分,}就是一个token。它没说“你少打了分号”,而是说“当我看到}时,按语法规则,前面应该有分号”,这暗示问题在}的上一行。

注意:编译器报错位置往往是“发现问题的地方”,不一定是“出错的地方”。比如少了一个{,编译器可能到几十行后才因匹配不上而报错。所以看到报错,第一反应不是改报错行,而是检查报错行的上一行结尾和上上一行。

3.7 断点七:main函数的参数argc和argv[]——命令行输入的另一扇门

教材第一章通常不提int main(int argc, char *argv[]),但它其实是main最本真的形态。argc(argument count)是命令行参数个数,argv(argument vector)是参数字符串数组。当你执行./hello Alice Bob,argc=3(./hello算一个),argv[0]="./hello",argv[1]="Alice",argv[2]="Bob"。

为什么现在就要知道?因为它是理解“程序如何与外界交互”的起点。scanf是从键盘读,argv是从命令行读——后者更高效,更适合自动化脚本。你可以用它改写hello.c:

#include <stdio.h> int main(int argc, char *argv[]) { if (argc > 1) { printf("Hello, %s!\n", argv[1]); } else { printf("Hello, World!\n"); } return 0; }

编译后执行./hello 张三,输出Hello, 张三!。这比每次运行都手动输入快得多。

实操技巧:argc和argv是C语言连接操作系统最直接的桥梁。后续学文件操作、网络编程时,你会发现几乎所有系统API都采用类似的“参数计数+参数数组”模式。现在理解它,等于提前拿到了一把通用钥匙。

4. 实操过程与核心环节实现:手把手完成4个示例的完整闭环

4.1 环境准备:3分钟搭建纯净编译环境(Windows/macOS/Linux通用)

不要用网上教程里复杂的MinGW安装包,直接用最轻量、最可控的方式:

  • Windows:下载 TDM-GCC (选tdm64-gcc-10.3.0-2.exe),安装时勾选“Add to PATH”,完成后打开CMD,输入gcc --version,显示版本即成功。
  • macOS:终端执行xcode-select --install,自动安装Command Line Tools(含GCC)。
  • Linux(Ubuntu/Debian):sudo apt update && sudo apt install build-essential。

提示:安装后务必验证gcc和make是否可用。很多初学者卡在第一步,不是代码问题,而是环境没配好。用which gcc确认路径,用gcc -v看详细版本。

创建项目目录:

mkdir c-beginner && cd c-beginner

所有代码都放在这里,避免路径混乱。

4.2 示例一:hello.c——建立第一个“编译-运行”闭环

代码内容(严格按教材,一个字符不差):

#include <stdio.h> int main(void) { printf("Hello, World!\n"); return 0; }

实操步骤与现场记录:

  1. 用记事本(Windows)/TextEdit(macOS,设为纯文本)/gedit(Linux)新建文件,保存为hello.c,编码必须选UTF-8无BOM(否则中文注释会乱码)。
  2. 打开终端,进入c-beginner目录,执行:
gcc hello.c -o hello
  • -o hello:指定输出可执行文件名为hello(Linux/macOS)或hello.exe(Windows)。不加-o,默认输出a.out或a.exe,不易识别。
  1. 执行程序:
./hello
  • Windows用户注意:CMD里用hello.exe,PowerShell里用.\hello.exe。
  • 输出应为:Hello, World!(注意末尾有换行,光标在下一行)。

关键验证点:

  • 如果报错gcc: command not found,环境未配置,回退到4.1节。
  • 如果报错undefined reference to 'printf',检查#include <stdio.h>是否拼写正确,是否少了<或>。
  • 如果输出Hello, World!但光标紧贴其后(无换行),说明\n被写成了\\n或/n,重新检查双引号内字符。

4.3 示例二:hello2.c——用转义字符控制输出位置

代码内容:

#include <stdio.h> int main(void) { printf("First line.\nSecond line.\n"); printf("Item 1:\tItem 2:\tItem 3:\n"); printf("Backspace\b test.\n"); return 0; }

实操重点与原理验证:

  • \n(换行):第一行输出后,光标跳到下一行开头。
  • \t(制表符):插入一个水平制表位(通常4或8个空格),用于对齐列。
  • \b(退格符):将光标左移一格,覆盖前一个字符。"Backspace\b test"中,\b让光标退回s的位置, (空格)覆盖s,t覆盖空格,最终显示Backspac test(e被t覆盖)。

现场测试命令:

gcc hello2.c -o hello2 && ./hello2 | od -c

观察输出:012(\n)、011(\t)、010(\b)的八进制码,确认转义字符被正确解析。

4.4 示例三:calc.c——引入变量与用户输入

代码内容:

#include <stdio.h> int main(void) { int a, b, sum; // 声明三个整型变量 printf("Enter first number: "); // 提示输入 scanf("%d", &a); // 读取整数,存入a的地址 printf("Enter second number: "); scanf("%d", &b); sum = a + b; // 计算和 printf("Sum is %d\n", sum); // 输出结果 return 0; }

实操避坑指南:

  • 输入缓冲区陷阱:连续两次scanf,如果第一次输入123后按回车,\n会留在输入缓冲区,第二次scanf可能直接读到\n而跳过等待。解决方案:在scanf后加getchar()吸收换行符,或统一用fgets读取整行再解析(进阶)。
  • 格式符匹配:%d只能读整数。如果用户输入abc,scanf会失败,a保持未初始化值(垃圾数)。可在scanf后加判断:
if (scanf("%d", &a) != 1) { printf("Invalid input!\n"); return 1; }
  • 变量初始化:虽然int a, b, sum;声明后值为0(全局变量)或随机(局部变量),但显式初始化更安全:int a = 0, b = 0, sum = 0;。

4.5 示例四:error_demo.c——5种经典错误的制造与修复

故意写错的代码(请逐行敲入,不要复制):

#include <stdio.h> int main(void) printf("Hello, World!\n") return 0; }

错误类型与修复过程:

错误位置GCC报错信息(节选)错误类型修复方法
main(void)后缺{error: expected '{' before 'printf'syntax在main(void)后加{
printf后缺;error: expected ';' before 'return'syntax在printf(...)后加;
return 0;前缺}error: expected '}' at end of inputsyntax在return 0;后加}
#include写成#inculdefatal error: stdio.h: No such file or directoryfatal修正拼写为#include
printf写成prinferror: implicit declaration of function 'prinf'implicit修正为printf

实操价值:每修复一个错误,就执行一次gcc,观察报错信息如何变化。你会发现,修复第一个{后,后续报错会减少;修复分号后,}的报错消失。这证明:编译器的错误是连锁反应,优先修复最靠前的语法错误。

5. 常见问题与排查技巧实录:来自真实训练营的12个高频问题速查表

5.1 编译阶段问题

问题现象可能原因排查命令解决方案
gcc: command not foundGCC未安装或PATH未配置echo $PATH(Linux/macOS) /path(Windows)重装GCC,确保安装时勾选“Add to PATH”
fatal error: stdio.h: No such file or directory头文件路径错误或GCC损坏gcc -v查看配置路径重装GCC,或检查是否误删了/usr/include
error: stray '\240' in program代码中混入了全角空格或中文标点cat -A hello.c显示所有不可见字符用纯文本编辑器重写,禁用智能引号
warning: incompatible implicit declaration of built-in function 'printf'忘了#include <stdio.h>gcc -E hello.c | grep printf确认头文件存在且拼写正确

5.2 运行阶段问题

问题现象可能原因排查命令解决方案
程序运行后窗口一闪而逝控制台程序执行完立即关闭./hello && read -p "Press any key..."(Linux/macOS)在return 0;前加getchar();暂停
printf输出无换行,文字挤在一起\n被写成\\n或遗漏./hello | od -c检查双引号内是否为真正的\n
scanf后程序直接结束,未等待输入输入缓冲区残留\nprintf("a=%d\n", a);打印变量值在scanf后加getchar();吸收换行符
scanf读入后变量值为0或极大负数&符号遗漏printf("a=%d, &a=%p\n", a, &a);确认scanf参数是&a而非a

5.3 逻辑与理解问题

问题现象根本原因教学类比行动建议
“为什么main必须返回int?我只想输出,不想返回!”操作系统需要退出状态码来判断程序成败就像快递签收单,必须写“已签收”或“拒收”,不能空白强制自己每写一个main,第一反应是return 0;
“#include <stdio.h>和#include "mylib.h"有什么区别?”< >从系统路径找," "从当前目录找<stdio.h>是官方说明书,"mylib.h"是自编的草稿纸自己写头文件时,一律用" "
“printf和puts都能输出,该用哪个?”printf支持格式化,puts只输出字符串+自动换行printf是瑞士军刀,puts是专用起子初学用printf,熟练后再学puts
“void main()在旧书里能用,为什么现在不行?”C89标准允许,C99/C11标准废除,现代编译器拒绝就像老式插头(两孔)被新国标(三孔)淘汰从第一天起,只写int main(void)或int main(int argc, char *argv[])

5.4 我踩过的坑:3个血泪教训分享

  1. 编辑器编码陷阱:某次用Windows记事本写代码,保存为ANSI编码,#include <stdio.h>里的<和>被转成乱码,GCC报invalid preprocessing directive。折腾2小时才发现是编码问题。教训:永远用VS Code、Sublime Text等专业编辑器,设置默认编码为UTF-8。

  2. 路径空格雷区:把项目放在C:\My Documents\c-code\,GCC报No such file or directory。因为My Documents含空格,命令行未加引号。教训:项目路径禁用空格和中文,用c_beginner代替c-beginner。

  3. return值滥用:曾用return 12345表示“程序成功”,结果在Linux脚本里被判定为失败(退出码>255会截断)。教训:return 0表示成功,return 1~127表示不同错误类型,永远遵守约定。

6. 后续可扩展方向:从第一章出发的3条进阶路径

第一章的终点,其实是整个C语言世界的入口。基于你此刻掌握的“编译-运行-报错-修复”闭环能力,我可以明确告诉你三条不绕弯的进阶路径:

路径一:深入“内存”视角(推荐给想学嵌入式/操作系统者)
下一步,把calc.c里的int a, b, sum;换成int a = 10, b = 20;,然后用GDB调试器单步执行:

gcc -g calc.c -o calc && gdb ./calc (gdb) break main (gdb) run (gdb) info registers # 查看CPU寄存器 (gdb) x/4xw &a # 查看变量a的内存内容(4个字,十六进制)

你会亲眼看到a的值10(0x0a)如何存储在内存地址中,&a如何指向这个地址。这比一百页教材更直观地揭示“变量即内存地址”这一本质。

路径二:打通“命令行”管道(推荐给想学Linux/运维者)
把hello.c改造成:

#include <stdio.h> int main(int argc, char *argv[]) { for (int i = 1; i < argc; i++) { printf("Arg %d: %s\n", i, argv[i]); } return 0; }

然后执行:

./hello apple banana | grep "apple" | wc -l

你将第一次体验C程序如何成为Linux命令链中的一环。后续可学fork/exec,自己实现简易shell。

路径三:连接“硬件”脉搏(推荐给电子爱好者)
用树莓派或ESP32,把printf("LED ON\n");替换成gpio_set_level(LED_GPIO, 1);。第一章练熟的gcc编译流程,无缝

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询