嘿,小朋友!或者正在学编程的大朋友,欢迎来到代码的世界。你是不是觉得C语言听起来很吓人,像什么“指针”、“内存”、“编译”这些词,感觉像是外星人说的话?别怕,今天我不讲那些枯燥的书本定义,我们把C语言想象成你正在搭积木,或者是在写一道超级详细的乐高说明书。只要你能看懂怎么给机器人下指令,你就能学会C语言。

第一章:我们到底在做什么?

首先,你要知道,电脑其实是个“笨笨”的家伙。它什么都懂,只要你把它说清楚。比如你想让它写“你好”,你不能直接对着它喊,你得写下一行字,告诉它:“嘿,把‘你好’这两个字显示在屏幕上。”

在C语言里,这行字就是代码。而那个把你写的代码翻译成电脑能听懂的“语言”的程序,叫做编译器。你可以把编译器想象成一个翻译官,你写的是中文(C语言),它把它翻译成英文(机器码),电脑才能执行。

第二章:Hello World!我们说的第一句话

在编程界有一个古老的传统,所有程序员学会写程序的第一步,都是让电脑在屏幕上打印出“Hello World”。这不是为了耍酷,而是为了确认你的电脑准备好了,而且你懂得怎么把文字显示出来。

我们用C语言来写这句话:

#include <stdio.h>

int main() {
    printf("Hello World!");
    return 0;
}

看不懂没关系,我们来拆解一下,就像拆一个快递盒子一样。

1. #include <stdio.h>

这一行是在告诉电脑:“嘿,我要用到一个工具箱,里面装着‘打印’和‘读入’功能的工具。” stdioStandard Input Output(标准输入输出)的缩写。就像你要画画,得先打开画笔盒一样。

2. int main()

这一行是程序的入口。想象一下,你要去一个很大的游乐园(你的程序),你肯定得从正门进去对吧?main 就是那个正门。int 的意思是,这个门出来时,你会带回来一个整数(数字),这就是后面那个 return 0 的意思。

3. { ... }

这两个大括号是程序的身体。所有你要电脑做的事情,都要塞进这两个括号里面。如果没有它们,电脑就不知道从哪里开始,到哪里结束。

4. printf("Hello World!");

这一行是最有意思的!printfprint formatted(打印格式化内容)的缩写,但你可以简单地把它记成“说这句话”。括号里是你想让电脑说的话。记住,文字一定要用双引号 "" 包起来,不然电脑会以为你在叫它一个奇怪的名字。分号 ; 是句子的句号,告诉电脑:“这一句说完了,继续下一句。”

5. return 0;

这一行是说:“嘿,程序跑完了,一切正常,没有报错。” 0 就像是一个“通关印章”。

第三章:变量——你的小盒子

现在你知道了怎么说话,接下来我们要学会怎么存东西。在C语言里,我们有一种东西叫变量

你可以把变量想象成一个个贴着标签的小盒子。你可以往盒子里放东西,也可以把里面的东西拿出来用。但是,每个盒子都有规定只能放某种东西:有的盒子只能放整数,有的只能放小数,有的只能放一个字符。

整数盒子:int

如果你要存年龄、数量、分数,就用 int

int age = 6; // 我有一个盒子叫age,里面放了数字6
int apples = 10; // 另一个盒子apples,放了10个苹果

小数盒子:floatdouble

如果你要存身高(1.5米)、价格(3.5元),就要用 floatdouble

float height = 1.45; // 身高1.45米
double price = 9.99; // 价格9.99元

字符盒子:char

如果你要存一个字母、一个汉字(注意:一个char只能存一个字符),就用 char。记住要用单引号 ''

char grade = 'A'; //  grade盒子里装的是字母A
char firstLetter = 'C'; // 装的是字母C

怎么把东西从盒子里拿出来?

我们用 printf占位符。就像填空游戏一样:

  • %d 是填整数 int 的空位
  • %f 是填小数 float 的空位
  • %c 是填字符 char 的空位
#include <stdio.h>

int main() {
    int age = 6;
    float height = 1.45;
    
    printf("我今年 %d 岁,身高 %.2f 米。\n", age, height);
    
    return 0;
}

运行这段代码,屏幕会显示:我今年 6 岁,身高 1.45 米。

注意看,%d 被替换成了 age 的值(6),%.2f 被替换成了 height 的值(1.45,.2 表示保留两位小数)。\n 是换行符,就像按了一下回车键。

第四章:条件判断——如果……就……

生活里充满了选择。如果下雨,我就带伞;如果没下雨,我就戴帽子。在C语言里,我们用 ifelse 来实现这个逻辑。

#include <stdio.h>

int main() {
    int score = 85;
    
    if (score >= 60) {
        printf("恭喜你,及格了!\n");
    } else {
        printf("很遗憾,下次加油哦!\n");
    }
    
    return 0;
}

这里,电脑会先检查括号里的条件 score >= 60(分数大于等于60吗?)。如果答案是“是”,它就执行 if 下面的代码;如果答案是“否”,它就执行 else 下面的代码。

你也可以用 &&(和)、||(或)、!(非)来组合更复杂的条件:

  • if (score >= 60 && score < 90):分数在60到90之间。
  • if (score < 60 || score > 100):分数小于60或者大于100。

第五章:循环——重复做同一件事

如果你要打印100遍“Hello”,难道要写100行 printf 吗?当然不用!我们可以用循环。C语言里有 for 循环和 while 循环,我们用 for 循环来举例,因为它最像数数。

#include <stdio.h>

int main() {
    for (int i = 1; i <= 10; i++) {
        printf("这是第 %d 次打招呼。\n", i);
    }
    
    return 0;
}

这段代码的意思是:

  1. int i = 1:我们从数字1开始数,把1放进盒子 i 里。
  2. i <= 10:只要 i 小于或等于10,就继续循环。
  3. i++:每循环一次,就把 i 增加1。
  4. 大括号里的代码:打印出“这是第 X 次打招呼”。

运行后,屏幕会显示:

这是第 1 次打招呼。
这是第 2 次打招呼。
...
这是第 10 次打招呼。

看,是不是很简单?循环就是让电脑做一个“复读机”。

第六章:函数——把你的技能打包

想象一下,你学会了一个新的魔术动作。如果每次变魔术都要重新教观众怎么把手指弯曲,那太累了。你可以把这个动作编成一个公式,叫做“魔术A”,以后只要说“表演魔术A”,大家就知道怎么做。

在C语言里,这就是函数。函数是一段可以重复使用的代码。我们可以自己写函数,也可以调用别人写好的函数(比如 printf 就是一个函数)。

#include <stdio.h>

// 这是我自定义的函数,用来计算两个数的和
int add(int a, int b) {
    int sum = a + b;
    return sum;
}

int main() {
    int result = add(5, 3); // 调用函数,把5和3传进去
    printf("5 加 3 等于 %d\n", result);
    
    return 0;
}

add 函数里:

  • int add(int a, int b):这个函数叫 add,它接受两个整数参数 ab,并且返回一个整数结果。
  • int sum = a + b;:在函数内部,把 ab 加起来,放进 sum 盒子。
  • return sum;:把 sum 的值还给你的程序。

main 函数里,我们调用 add(5, 3),电脑会去执行 add 函数里的代码,算出结果是8,然后把这个8赋给 result 变量。

函数的好处是,如果你以后要算 10 + 20,只需要再写一行 add(10, 20),而不需要重新写一遍加法的逻辑。

第七章:数组——一排整齐的盒子

有时候,一个变量不够用。比如你要存一个班级10个同学的成绩。难道你要写 int score1, score2, ... score10; 吗?那太麻烦了!我们可以用数组

数组就像是一排连在一起的盒子,每个盒子都有一个编号(下标),从0开始。

#include <stdio.h>

int main() {
    // 定义一个有5个格子的数组,用来存5个学生的成绩
    int scores[5] = {85, 90, 78, 92, 88};
    
    // 取出第3个学生的成绩(注意:下标从0开始,所以第3个是scores[2])
    printf("第3个学生的成绩是:%d\n", scores[2]);
    
    // 用循环打印所有成绩
    for (int i = 0; i < 5; i++) {
        printf("第 %d 个学生的成绩是:%d\n", i + 1, scores[i]);
    }
    
    return 0;
}

数组的下标是从 0 开始的,这是很多新手(包括大人)最容易犯错的地方。第一个格子的编号是0,第二个是1,第三个是2……所以 scores[2] 实际上是第三个成绩,也就是78分。

第八章:指针——盒子的门牌号(重点!)

好了,前面都是基础,现在我们要进入C语言的灵魂——指针。我知道,很多教程一讲指针就绕晕人,什么“地址”、“引用”、“解引用”……听得人头大。

别急,我们用寄快递来比喻指针。

1. 变量是什么?

变量是你住的一个房间。房间里有家具(数据)。比如 int a = 10; 就像是你住在一个房间里,房间里有一个叫“10”的玩具。

2. 地址是什么?

每个房间都有一个门牌号,用来定位这个房间在哪里。在电脑里,内存就像一个大公寓楼,每个房间(变量)都有自己的门牌号,这个门牌号就是地址

3. 指针是什么?

指针就是那个门牌号的纸条。它本身不是房间,也不是玩具,它只是一张写着“这个玩具在302房间”的纸条。

4. 怎么操作指针?

我们需要两个符号:

  • & (取地址符):意思是“给我这个房间的门牌号”。
  • * (解引用符):意思是“给我这个门牌号对应的房间里的东西”。

我们来看代码:

#include <stdio.h>

int main() {
    int a = 10;       // 1. 我在房间里放了一个玩具,值是10
    int *p;           // 2. 我准备了一张空白的纸条,专门用来写门牌号(指针变量)
    
    p = &a;           // 3. 我把a房间的门牌号,写在纸条p上
    
    printf("a的值是:%d\n", a);           // 打印玩具的值:10
    printf("a的门牌号是:%p\n", &a);      // 打印a房间的门牌号(比如:0x7fff5fbff6bc)
    printf("纸条p上的门牌号是:%p\n", p); // 打印纸条p上的门牌号(应该和上面一样)
    
    printf("通过纸条找到的玩具是:%d\n", *p); // 关键!用 *p 意思是“去纸条p指的那个房间,把玩具拿出来”
    
    return 0;
}

运行结果可能是这样的:

a的值是:10
a的门牌号是:0x7fff5fbff6bc
纸条p上的门牌号是:0x7fff5fbff6bc
通过纸条找到的玩具是:10

看到了吗?*p 的结果和 a 的结果是一样的,因为它们指向同一个地方。

5. 指针有什么用?

你可能会问:“既然 a*p 一样,我直接用 a 不就行了吗?为什么要绕弯子?”

好问题!指针的真正威力在于修改。想象一下,你有一个大箱子(数组),里面有100个苹果。如果你想把第5个苹果换成香蕉,你可以直接走过去换(用数组下标 a[4])。但是,如果你想让这个动作变得灵活,比如写一个函数,专门负责“把某个位置的苹果换成香蕉”,你就需要把“第5个苹果在哪里”告诉这个函数。

这时候,指针就派上用场了。你可以把苹果所在的地址传给函数,函数就能找到那个苹果并修改它,而不需要把整个大箱子搬过去。

#include <stdio.h>

// 这个函数接收一个整数的地址,并把那个位置的数改成99
void changeValue(int *ptr) {
    *ptr = 99; // 去ptr指的那个房间,把里面的东西改成99
}

int main() {
    int a = 10;
    int *p = &a;
    
    printf("修改前,a的值是:%d\n", a);
    
    changeValue(p); // 把a的地址传给函数
    
    printf("修改后,a的值是:%d\n", a); // 看看,a变成了99!
    
    return 0;
}

注意,在 main 函数里,我们没有传 a 的值,而是传了 p(也就是 &a,a的地址)。函数 changeValue 接收到地址后,通过 *ptr = 99 直接修改了 a 的值。

这就是指针最强大的地方:通过地址,间接地修改内存中的数据。

6. 指针和数组的关系

在C语言里,指针和数组是好朋友。数组的名字本身就是一个指针,指向数组的第一个元素。

int scores[5] = {85, 90, 78, 92, 88};

// scores 就是 &scores[0],即第一个元素的地址
printf("第一个成绩:%d\n", scores[0]);      // 用下标访问
printf("第一个成绩:%d\n", *scores);        // 用指针访问,*scores 就是解引用第一个元素的地址

// scores + 1 就是第二个元素的地址
printf("第二个成绩:%d\n", *(scores + 1));  // 指针算术运算,* (scores+1) 就是第二个元素

看,*(scores + 1)scores[1] 是完全一样的!理解这一点,你就理解了C语言数组和指针的核心。

第九章:字符串——一串字符的盒子

在C语言里,没有专门的“字符串”类型。字符串其实就是一个字符数组,并且最后一个字符是空字符 \0,用来告诉电脑“故事讲完了”。

#include <stdio.h>
#include <string.h> // 引入字符串处理工具库

int main() {
    char name[20] = "Agnes"; // 定义一个字符数组,存放字符串"Agnes"
                             // 注意:C语言会自动在末尾加上 '\0'
    
    printf("我的名字是:%s\n", name); // %s 是字符串的占位符
    
    // 计算字符串长度
    int length = strlen(name); // strlen 是 string length 的缩写
    printf("名字的长度是:%d\n", length);
    
    return 0;
}

字符串的处理在C语言里比较麻烦,因为你需要手动管理那个 \0。但在实际编程中,我们通常会用 strlenstrcpystrcmp 等函数来处理,这些函数都在 <string.h> 头文件里。

第十章:结构体——定制你的盒子

有时候,一个盒子不够用。比如你要存一个学生的信息,有名字(字符串)、年龄(整数)、身高(小数)。如果分开存,会很乱。我们可以用结构体,把多个不同类型的变量打包成一个“超级盒子”。

”`c #include #include

// 定义一个结构体,叫 Student struct Student {

char name[50];   // 名字
int age;         // 年龄
float height;    // 身高

};

int main() {

// 创建一个 Student 类型的变量
struct Student s1;

// 给结构体的成员赋值