news 2026/11/4 12:15:32

记录学习c语言第一天——数组和函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
记录学习c语言第一天——数组和函数

C语言学习记录(一):从数组到指针入门

初学者视角的完整笔记:知识点整理 + 代码示例 + 踩坑复盘 + 后续计划。

前言

最近在系统学习 C 语言,今天集中攻克了「数组 → 字符串 → 二维数组 → 函数 → 指针入门」这一串内容。作为初学者,我明显感觉到这几个知识点是连在一起的:数组是基础,字符串是特殊的数组,二维数组是数组的数组,函数用来打包逻辑,而指针则是理解 C 语言「地址」思维的第一步。

这篇博客既是学习记录,也是踩坑复盘,希望能帮到同样在入门的同学。


一、数组:一排从 0 开始编号的格子

1.1 为什么需要数组

如果一个变量只能存一个值:

int a = 10; int b = 20; int c = 30;

那要存 100 个学生的成绩,难道写 100 个变量?数组就是「一排连续的小格子」,每个格子存同类型的数据,用一个名字管理一整排。

成绩数组 score: ┌────┬────┬────┬────┬────┐ │ 90 │ 85 │ 78 │ 92 │ 66 │ └────┴────┴────┴────┴────┘ [0] [1] [2] [3] [4] ← 下标

1.2 声明与初始化

int score[5]; // 5 个格子 int score[5] = {90, 85, 78, 92, 66}; // 声明时直接给值 int score[] = {90, 85, 78, 92, 66}; // 不写个数,让编译器自己数

1.3 下标从 0 开始(新手最容易错)

score[5]一共有 5 个格子,编号是 0~4,没有 score[5]。

score[0] = 90; // 第 1 个格子 score[4] = 66; // 第 5 个(最后一个) // score[5] = 10; // ❌ 越界,没有这个格子

1.4 数组 + for 循环

#include <stdio.h> int main() { int score[5] = {90, 85, 78, 92, 66}; for (int i = 0; i < 5; i++) // i 从 0 到 4 { printf("第 %d 个学生:%d 分\n", i + 1, score[i]); } return 0; }

注意是i < 5而不是i <= 5,因为最后一个下标是 4。

1.5 例子:算平均分

#include <stdio.h> int main() { int score[5] = {90, 85, 78, 92, 66}; int sum = 0; for (int i = 0; i < 5; i++) sum += score[i]; printf("平均分 = %d\n", sum / 5); return 0; }

1.6 必须记住的三点

  1. 下标从 0 开始,int a[5]的下标是 0~4。
  2. 不能越界,a[5]是错的,程序不一定报错,但会出现诡异的 bug。
  3. 数组里所有元素类型相同,不能又装 int 又装 float。

二、踩坑:中文输出乱码

2.1 现象

程序里的中文全变成了乱码,但数字正常:

绗?1 涓鐢燂細90 鍒?

2.2 原因

源文件是 UTF-8 编码,但 Windows 终端默认用 GBK 显示。UTF-8 的中文字节被 GBK 解读,就成了乱码。数字和字母没事,是因为 ASCII 在两种编码里一致。

2.3 解决

方法一(最简单):把文件用 GBK 编码保存。VS Code 右下角点击UTF-8→ 通过编码保存 → 选 GBK。

方法二:运行前在终端执行chcp 65001,让终端用 UTF-8。

方法三:程序里自己切换:

#include <stdio.h> #include <stdlib.h> int main() { system("chcp 65001 > nul"); // 切换成 UTF-8 // ... }

前提是源文件本身是 UTF-8。

一句话:文件编码和终端编码要一致,要么都用 GBK,要么都用 UTF-8。


三、字符串:其实就是字符数组

3.1 字符数组

char c[5]; c[0] = 'h'; c[1] = 'i';

'h'是字符,"hi"是字符串,别搞混。

3.2 关键约定:末尾有\0

C 语言没有专门的字符串类型,字符串就是 char 数组,并且约定以\0结尾。

"hi"在内存里其实是 3 个格子:

┌───┬───┬────┐ │ h │ i │ \0 │ └───┴───┴────┘ [0] [1] [2]

那个\0告诉程序「字符串到这里结束」。

3.3 读入和输出

#include <stdio.h> int main() { char name[20]; printf("请输入名字:"); scanf("%s", name); // 注意:name 前面不用 & printf("你好,%s\n", name); return 0; }

两个要点:

  • scanf("%s", name)不加&,因为数组名本身就是地址。
  • %s读入遇到空格就停。

3.4 求长度与比较(理解\0)

自己写求长度:

int len = 0; while (s[len] != '\0') // 没遇到 \0 就一直数 len++;

自己写比较:

int i = 0; while (a[i] == b[i] && a[i] != '\0') i++;

实际开发直接用<string.h>:

#include <string.h> strlen(s); // 求长度 strcmp(a, b); // 相等返回 0,a<b 返回负数,a>b 返回正数 strcpy(a, b); // 把 b 复制到 a

注意:strcmp(a, b) == 0才是相等,不是== 1。


四、二维数组:表格

4.1 概念

二维数组就是「数组的数组」,有行有列。比如 3 个班、每班 5 人的成绩:

学生0 学生1 学生2 学生3 学生4 1班 90 85 78 92 66 2班 88 76 95 70 81 3班 79 83 91 68 87
int score[3][5]; // 3 行 5 列

4.2 访问与初始化

score[0][1] = 85; // 第 0 行、第 1 列 int score[3][5] = { {90, 85, 78, 92, 66}, // 第 0 行 {88, 76, 95, 70, 81}, // 第 1 行 {79, 83, 91, 68, 87} // 第 2 行 };

4.3 双层循环遍历

for (int i = 0; i < 3; i++) // 外层:i 走行 { for (int j = 0; j < 5; j++) // 内层:j 走列 printf("%d ", score[i][j]); printf("\n"); }

4.4 例子:求各班平均分

#include <stdio.h> int main() { int score[3][5] = { {90, 85, 78, 92, 66}, {88, 76, 95, 70, 81}, {79, 83, 91, 68, 87} }; for (int i = 0; i < 3; i++) { int sum = 0; // 关键:写在每个班开始处,每行重置 for (int j = 0; j < 5; j++) sum += score[i][j]; printf("第 %d 班的平均分 = %d\n", i + 1, sum / 5); } return 0; }

关键点:sum必须声明在外层循环内部,这样每换一行就重置为 0,不会把上一行的和累加进来。


五、函数:把代码打包

5.1 函数结构

返回值类型 函数名(参数列表) { 函数体 return 值; }

5.2 例子:求最大值

#include <stdio.h> int max(int a, int b) { if (a > b) return a; else return b; } int main() { printf("%d\n", max(3, 7)); // 7 return 0; }

5.3 三个关键点

  1. 参数是「输入」,return是「输出」。
  2. 函数要写在main前面(先定义后使用)。
  3. 没有返回值就用void。

5.4 例子:阶乘函数

#include <stdio.h> int fact(int n) { int ret = 1; for (int i = 1; i <= n; i++) ret *= i; return ret; } int main() { int t; printf("请输入一个整数:"); scanf("%d", &t); printf("%d! = %d\n", t, fact(t)); return 0; }

这里t传给fact是值传递,函数内部改的是副本,外面的t不受影响——这正是函数的好处。


六、指针入门

6.1 地址

每个变量在内存里都有地址,就像宿舍房间号。

int n = 10;

6.2&和*

int n = 10; int *p = &n; // p 存 n 的地址
  • &n:取 n 的地址。
  • int *p:声明一个指针变量。
  • *p:通过地址访问/修改 p 指向的变量。

6.3 完整例子

#include <stdio.h> int main() { int n = 10; int *p = &n; printf("n = %d\n", n); // 10 printf("&n = %p\n", &n); // 一串十六进制地址 printf("p = %p\n", p); // 和 &n 一样 printf("*p = %d\n", *p); // 10 *p = 20; // 通过 p 修改 n printf("n = %d\n", n); // 20 return 0; }

6.4 解开心结:scanf 为什么加&

scanf需要知道「把读到的值写到哪个地址」,所以要&n:

int n; scanf("%d", &n);

而数组名本身就是首元素地址,所以不用&:

char name[20]; scanf("%s", name);

七、我踩过的坑(重点复盘)

  1. for 循环三段式写错:for(n>1; n--)把条件当成了初始化,缺了真正的条件。正确写法是for(初始化; 条件; 步进)。
  2. 打印了被循环改坏的变量:循环把变量改成了别的值,还拿它打印。要用副本保存原始值。
  3. 变量命名不达意:把「最大值」命名成sum。名字要反映它装的是什么。
  4. 遍历数组从 i=1 开始,漏掉第 0 个元素:求和、统计两遍都从 1 开始,漏了score[0]。遍历数组基本都从 0 开始。
  5. 没看清题目要求:题目要「个数」,却打印了每个元素。动手前先确认要计数、求和还是打印每个值。
  6. 中文乱码:文件编码和终端编码不一致。

八、练习题清单

  1. 输入 5 个整数,倒序打印。
  2. 输入 5 个整数,求最大值。
  3. 输入 5 个整数,求平均分并统计高于平均分的人数。
  4. 二维数组score[3][5],求每个班的平均分。
  5. 写函数fact(n)求阶乘。

九、下一步计划

  1. 先不看答案,把上面的 5 道练习重写一遍。
  2. 重点巩固数组下标范围、for三段式。
  3. 再学指针进阶:
    • 值传递 vs 地址传递;
    • 经典例子:写swap函数交换两个数;
    • 指针和数组的关系(a[i]和*(a+i))。
  4. 之后再看结构体struct。

总结

今天最大的收获不是记住了多少语法,而是理解了几个核心思想:

  • 数组是「同类型数据 + 下标」;
  • 字符串是「char 数组 +\0」;
  • 二维数组是「数组的数组 + 双层循环」;
  • 函数是「输入参数 + 返回结果」的打包;
  • 指针是「地址」的思维。

也踩了不少坑,但每个坑都让我对 C 语言的细节理解更深了一层。继续加油。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/4 12:15:25

一个 authorized_keys 字段,解决了多 Agent 系统的身份问题

一个 authorized_keys 字段&#xff0c;解决了多 Agent 系统的身份问题 多智能体源码协作系列 第 2 篇 / 共 8 篇 上一篇&#xff08;第 1 篇 问题定义&#xff09;&#xff1a;CSDN 本文所有路径、席位名、项目名均为泛化示例&#xff0c;可直接复制使用。 一、结论先行 在…

作者头像 李华
网站建设 2026/11/4 12:15:09

真绝了,国产模型 Token 自由了!

大家好&#xff0c;我是二哥呀。 前几天我不是去大学讲课了嘛&#xff0c;问了很多同学&#xff0c;都说顶级模型太贵了&#xff0c;根本用不起&#xff0c;他们想要更多的赛博鸡蛋。 这不&#xff0c;正巧赶上 1024 开发者节&#xff0c;讯飞发布了全新的星火 X2.6&#xff08…

作者头像 李华
网站建设 2026/11/4 12:14:39

emacs 文件管理Dired, the Directory Editor

Dired&#xff1a;目录编辑器 Dired 会创建一个 Emacs Buffer&#xff0c;其中包含某个目录的文件列表&#xff0c;并且还可以选择性地包含该目录下的一些子目录的内容。 你可以使用 Emacs 的常规命令在这个 Buffer 中移动和浏览&#xff0c;也可以使用 Dired 专用命令对列表中…

作者头像 李华
网站建设 2026/11/4 12:13:39

Kestrel_VLLM - 30 · MTP 头适配:十五个张量与一个不存在的 oracle

30 MTP 头适配&#xff1a;十五个张量与一个不存在的 oracle 一句话&#xff1a;Qwen3.5-27B 除 64 层主干外还自带一个模型内投机草稿头 MTP&#xff08;Multi-Token Prediction&#xff0c;多 token 预测&#xff09;——它不在主干里、没有官方实现可对照&#xff0c;却决定…

作者头像 李华
网站建设 2026/11/4 12:13:26

破解 FAU 端面 1 微米崩缺检测的景深困局

1. 高分辨率与浅景深 要看清 FAU&#xff08;Fiber Array Unit&#xff0c;光纤阵列单元&#xff09;端面上 1 微米级的崩缺&#xff0c;相机必须配高倍率镜头。这是光学检测里最朴素的常识&#xff1a;分辨率越高&#xff0c;能分辨的细节越小。 但高倍率镜头的光学特性决定了…

作者头像 李华