Skip to content

1.6 数组

计算机程序设计 · C语言 · 1.6 数组(零基础讲义)

数组

🎯 一句话秒杀:数组是同一类型数据的集合,用下标访问每个元素。一维数组就像一排格子,二维数组像一张表格。


① 📊【历年真题考情】

本章(数组)在广东专升本计算机统考中的位置:

项目结论
出题频次⭐⭐⭐⭐⭐(五星必考)——2026 考纲全解标注"数组 ⭐⭐⭐,能独立手推和编写完整程序";编程大题的地基,几乎年年考
常考题型单选(2024 单选14、2026 单选3/4)、判断(2024 判断2/7)、填空(2024 填空2)、编程大题(2024 数组平均值)
预估分值10~30 分 / 200 分(约 5%~15%,与函数/指针并列最高分值模块)
考纲归属2026 考纲「复合数据」考点5(一维/二维、字符数组、字符串函数)

考场真实出现过的高频题:

  • 2024 判断2:数组下标从 1 开始?→ (从 0 开始)
  • 2024 判断7:二维数组按行优先存储 →
  • 2024 填空2:strlen(strcpy(s1,s2))2(strcpy 返回目标地址 + strlen 嵌套)
  • 2024 单选14:strlen("abcd")4(不含 \0
  • 2026 单选3:strlen("Guangdong")9
  • 2026 单选4:int a[5]={1,2,3} → a[4] = 0(部分初始化自动补 0)
  • 2024 应用大题:数组求平均值

🎯 学习目标:学完本章,你能 ① 一眼看出 strlen/sizeof 的结果;② 判断数组初始化后的每个元素值;③ 手推 strcpy/strcmp 嵌套表达式;④ 写出数组求和/平均值的完整程序——这四类题就是本章真题的全部考法。


② 🗣️【零基础大白话引入】

数组是什么? 想象一排储物柜(一维数组):

  • 柜子编号从 0 开始(不是 1!):第 1 个柜子是 a[0],第 2 个是 a[1]……
  • 每个柜子只能放同一种东西(同一类型)
  • 你报"3 号柜",就能直接打开 a[3]

二维数组 = 超市货架:有行有列(如 3 行 4 列),a[i][j] 表示第 i 行第 j 列的格子。

字符数组 = 一串字符排队"Hello" 其实是 6 个格子(H e l l o + 一个隐藏的 \0 结束标志)。字符串函数(strlen 等)就是靠这个 \0 知道"字符串到哪结束"。

💡 本章主线:一维数组(一排格子)→ 二维数组(表格)→ 字符数组(字符串)→ 字符串函数。数组是编程大题的地基——求和、排序、找最大全用它。


③ 📖【正式核心知识点讲解】

本章知识点 = 考纲要求 + 历年真题实际考过的内容。真题未考、考纲不作要求的超纲内容已剔除或标注"了解"。

3.1 一维数组

定义与初始化

c
类型 数组名[元素个数];
c
int a[5];                    // 定义5个整型元素,a[0]~a[4]
int a[5] = {1, 2, 3, 4, 5};  // 完全初始化
int a[5] = {1, 2, 3};         // 部分初始化 → a={1,2,3,0,0}
int a[] = {1, 2, 3, 4, 5};   // 自动推断长度为5
int a[5] = {0};               // 全部初始化为0

3.1.1 部分初始化自动补 0(2026 单选4 必考)

只给部分初值时,剩余元素自动初始化为 0

c
int a[5] = {1, 2, 3};
// 结果:a = {1, 2, 3, 0, 0}
// a[3] = 0, a[4] = 0

2026 单选4int a[5] = {1, 2, 3};a[4] 的值是 → A. 0(不是随机值!) 陷阱:选项 C"随机值"是给"以为未初始化的内存是垃圾值"的同学准备的——部分初始化会补 0

数组的引用

c
a[0] = 10;        // 第一个元素赋值
a[4] = a[0] + 1;  // 最后一个元素
printf("%d", a[i]);  // 通过变量下标访问

🚨 红牌警告

数组下标从0开始!(2024 判断2) a[5] 的合法下标是 0~4,没有 a[5]C语言不检查下标越界! a[10] = 5; 编译能通过但会访问非法内存(程序可能崩溃——运行错误,2026 单选8 关联) 定义时不能动态指定大小: int n; scanf("%d",&n); int a[n]; — C99支持变长数组(VLA),但考试一般不考虑

2024 判断2:"数组的下标从 1 开始" → (下标从 0 开始,int a[5] 合法下标 0~4)

一维数组在内存中的存储

c
int a[5] = {10, 20, 30, 40, 50};
内存:| a[0] | a[1] | a[2] | a[3] | a[4] |
地址:| 0x00 | 0x04 | 0x08 | 0x0C | 0x10 |  ← 每个int占4字节

数组名 = 首元素地址(常量,不能修改),即 a == &a[0]

3.2 二维数组

定义与初始化

c
类型 数组名[行数][列数];
c
int a[3][4];                     // 3行4列,共12个元素
int a[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}};  // 按行初始化
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};           // 按内存顺序
int a[3][4] = {{1}, {0,2}, {3}};  // 部分初始化

3.2.1 二维数组部分初始化(真题风格)

c
int a[3][4] = {{1}, {0, 2}, {3}};
// 第1行:{1, 0, 0, 0}
// 第2行:{0, 2, 0, 0}
// 第3行:{3, 0, 0, 0}
// 未指定的元素全部补 0

数组的引用

c
a[0][0] = 1;      // 第1行第1列
a[2][3] = 12;     // 第3行第4列

🔑 秒杀秘籍——行和列

c
int a[3][4];
// 3行4列 → 行下标 0~2,列下标 0~3
// 访问 a[i][j] → 第 i+1 行,第 j+1 列
// 共 3×4 = 12 个元素

二维数组在内存中的存储(2024 判断7 必考)

按行优先存储:
a[0][0] → a[0][1] → a[0][2] → a[0][3] →
a[1][0] → a[1][1] → a[1][2] → a[1][3] →
a[2][0] → a[2][1] → a[2][2] → a[2][3]

二维数组行优先存储:逻辑表格 → 连续内存

2024 判断7:"二维数组在内存中按行优先顺序存储" → 记忆:先存满一行,再存下一行(就像读书从左到右、从上到下)。

🚨 红牌警告——二维数组定义时行数可省略,列数不可

c
int a[][4] = {{1,2},{3,4,5},{6}};  // ✅ 自动推断行数=3
int a[3][] = {...};                  // ❌ 编译错误!列数不能省略

💡 为什么列数不能省?因为按行优先存储,编译器要知道"一行几个"才能算出 a[i][j] 的地址。

3.3 字符数组与字符串

字符数组

c
char str[10];                          // 存放10个字符
char str[10] = {'H','e','l','l','o'};  // 字符逐个赋值
char str[10] = "Hello";                 // 字符串常量初始化 ✅
char str[] = "Hello";                   // 自动推断长度=6(含\0)

字符串结束标志 \0

c
char s1[] = "Hello";     // 实际占6字节:H e l l o \0
char s2[] = {'H','e','l','l','o'};  // 占5字节:没有\0!

字符串以 \0(ASCII=0)结尾。库函数(如 puts, strlen)靠 \0 判断结束

🚨 红牌警告

char s[] = "Hello";sizeof(s)=6(含\0),strlen(s)=5(不含\0) char s[5] = "Hello";空间不够! 存不下\0,编译警告

3.3.1 strlen vs sizeof 逐步计算(2024/2026 必考)

c
char s[] = "Guangdong";   // 9 个可见字符 + 1 个 '\0'
printf("%d", strlen(s));  // 9(只数可见字符,不含 \0)
printf("%d", sizeof(s));  // 10(占多少字节,含 \0)
表达式结果原因
strlen("abcd")4数可见字符,不含 \0(2024 单选14)
sizeof("abcd")5含末尾 \0
strlen("Guangdong")99 个可见字符(2026 单选3)
sizeof("Guangdong")109 字符 + \0

2026 单选3strlen("Guangdong") = B. 9sizeof 则 = 10

字符串处理函数(重点!)

函数原型功能使用注意
putsputs(str)输出字符串+换行遇到\0结束
getsgets(str)读一行字符串⚠️ 不安全,不检查边界
strlenstrlen(str)返回字符串长度不含\0
strcpystrcpy(s1,s2)复制s2到s1目标要够大
strcatstrcat(s1,s2)s2接到s1末尾目标要够大
strcmpstrcmp(s1,s2)比较两个字符串相等返回0
c
#include <string.h>

char s1[20] = "Hello";
char s2[] = "World";

printf("%d", strlen(s1));        // 5
strcpy(s1, s2);                  // s1 = "World"
strcat(s1, "!");                 // s1 = "World!"
int cmp = strcmp("abc", "abd");  // 负数('c'<'d')

3.3.2 strcpy 嵌套陷阱(2024 填空2 必考)

strcpy 的返回值是目标串的地址——所以可以嵌套在 strlen 里

c
#include <stdio.h>
#include <string.h>

int main() {
    char s1[20] = "Hello";
    char s2[] = "Hi";
    printf("%d", strlen(strcpy(s1, s2)));   // 嵌套!
    return 0;
}

逐层推演:

  1. strcpy(s1, s2):把 "Hi" 拷到 s1 → s1 变成 "Hi"返回值是 s1 的地址
  2. strlen(strcpy(...)):对返回的 s1 数长度 → strlen("Hi") = 2
  3. 输出:2

2024 填空2printf("%d", strlen(strcpy(s1, s2)));2 陷阱:strcpy 返回值是目标地址,不是拷贝后的字符串——嵌套使用时先执行 strcpy 再 strlen。

🚨 红牌警告——strcmp 返回值是重点!

strcmp(s1, s2):

  • 返回 0 → s1 == s2(相等!)
  • 返回 <0 → s1 < s2(字典序靠前)
  • 返回 >0 → s1 > s2

不能像比较数字那样写 if (strcmp(s1, s2) == 0) 才能判断相等! 坑:if (strcmp(s1, s2)) — 这是不相等时为真(0为假,非0为真)

🔑 秒杀秘籍

strcpystrcat 的返回值都是目标串的地址——支持链式调用 strlen 返回的类型是 size_t(无符号整型) strcmp 比较的是ASCII码的字典序,不是长度

3.4 数组与循环(编程大题基础 · 2024 应用)

数组最经典的应用就是配合循环做求和、求平均值、找最大最小——编程大题必备。

c
#include <stdio.h>

int main() {
    int a[10] = {85, 72, 93, 68, 80, 76, 90, 83, 78, 88};
    int sum = 0, i;
    for (i = 0; i < 10; i++) {
        sum += a[i];
    }
    printf("平均值 = %.1f\n", sum / 10.0);
    return 0;
}

逐步推演:

  1. sum = 0 初始化
  2. 循环 i=0~9:sum += a[i] 累加 10 个数
  3. sum = 85+72+...+88
  4. sum / 10.0注意用 10.0 不是 10(否则整数除法截断)
  5. 输出平均值(保留 1 位小数)

2024 应用大题:数组求平均值的标准写法——循环累加 + 除以个数(注意用浮点除法)。


④ 🧪【真题同源例题】

例题 1:入门基础题(先热热身)

c
int a[5] = {1, 2, 3};
printf("%d %d", a[3], a[4]);

逐项推演:

  1. 只给了 3 个初值:
  2. 剩余元素自动补 0:a = {1, 2, 3, 0, 0}
  3. a[3] = 0a[4] = 0
  4. 输出:0 0

例题 2:2026 真题改编(部分初始化)

已知 int a[5] = {1, 2, 3};,则 a[4] 的值是(  )

A. 0  B. 3  C. 随机值  D. 越界

逐项分析:

  1. 部分初始化:{1,2,3} → 剩下 a[3]、a[4] 自动补 0
  2. A 0 ✅(正确)
  3. B 3:a[4] 不是 3 ❌
  4. C 随机值:部分初始化会补 0,不是随机 ❌
  5. D 越界:a[4] 合法(下标 0~4)❌

✅ 答案 A(2026 单选4 原题)

例题 3:2024 真题改编(strcpy 嵌套陷阱)

c
char s1[20] = "Hello";
char s2[] = "Hi";
printf("%d", strlen(strcpy(s1, s2)));

逐层推演:

  1. 先执行内层 strcpy(s1, s2):把 "Hi" 拷入 s1
  2. strcpy 返回 s1 的地址
  3. 外层 strlen(返回的地址):数 s1 的长度 = strlen("Hi") = 2
  4. 输出:2

✅ 对应 2024 填空2,答案 2。关键:strcpy 返回目标地址,不是"拷贝后字符串"。

例题 4:2024 真题改编(strlen vs sizeof)

char s[] = "abcd";strlen(s)sizeof(s) 分别是(  )

A. 4, 5  B. 5, 4  C. 4, 4  D. 5, 5

逐项推演:

  1. strlen(s):数可见字符 a,b,c,d → 4(不含 \0)
  2. sizeof(s):数组占 5 字节(4 字符 + \0)→ 5
  3. 答案:A. 4, 5

✅ 对应 2024 单选14(strlen("abcd")=4)和 2026 单选3(strlen 不含 \0)。

例题 5:编程大题示例(数组平均值 · 2024 应用)

输入 10 个整数存入数组,计算并输出平均值(保留 1 位小数)。

c
#include <stdio.h>

int main() {
    int a[10];
    int i, sum = 0;
    for (i = 0; i < 10; i++)
        scanf("%d", &a[i]);
    for (i = 0; i < 10; i++)
        sum += a[i];
    printf("平均值 = %.1f\n", sum / 10.0);
    return 0;
}

逐步推演:

  1. 定义数组 a[10](10 个整数)
  2. 第一个循环:scanf("%d", &a[i]) 读入 10 个数(注意 &
  3. 第二个循环:sum += a[i] 累加
  4. sum / 10.0:浮点除法(不是 sum/10,否则截断)
  5. 输出保留 1 位小数

✅ 这是 2024 应用大题的完整写法——数组 + 循环 + 浮点除法三件套。


⑤ ⚠️【历年真题高频扣分坑】

#陷阱错误做法正确做法出处
1strlen 算上 \0strlen("abcd")=5strlen 不含 \0,=42024 单选14
2部分初始化当随机a[4] 以为是随机值部分初始化自动补 02026 单选4
3下标从 1 开始以为 a[1] 是第一个下标从 0 开始2024 判断2
4strcpy 返回值误解以为返回值是拷贝后的串strcpy 返回目标地址(可嵌套)2024 填空2
5strcmp 判断反if(strcmp(s1,s2)) 当相等strcmp==0 才是相等经典
6sizeof vs strlensizeof("ab")=2sizeof 含\0=32026 单选3
7二维数组列数省略int a[3][]列数不能省略(行可省)经典
8行优先写成列优先二维地址按列算按行优先存储2024 判断7
9数组越界当编译错误以为越界编译能发现越界是运行错误2026 单选8
10平均值整数除法sum/10 截断sum/10.0 浮点除法2024 应用
11strcat 目标不够大小数组接长串目标要足够大经典
12数组名当可变对数组名 a++数组名是常量指针经典

📌 最值钱的一条:第 4 条(strcpy 返回目标地址)是 2024 填空2 的核心——"嵌套函数调用从内往外算" 是填空题的通杀技巧。


⑥ 📝【课后自测练习题】

1. 已知 int a[5] = {1, 2, 3};,则 a[3] 的值是(  )(2026 真题风格)

A. 0  B. 3  C. 随机值  D. 越界


2. char s[] = "abc";strlen(s)sizeof(s) 分别是(  )(2024 真题风格)

A. 3, 4  B. 4, 3  C. 3, 3  D. 4, 4


3. 执行 printf("%d", strlen(strcpy(s1, "Hi")));(s1 已定义)输出(  )(2024 真题风格)

A. 2  B. 3  C. 4  D. 1


4. 判断:二维数组在内存中按列优先顺序存储。(  )(2024 真题风格)

A. 正确  B. 错误


5. 编写程序:输入 5 个整数存入数组,输出它们的和。(编程大题风格)



👆 点击展开参考答案与解析

第1题A. 0

  • 部分初始化 {1,2,3} → a[3]、a[4] 自动补 0(2026 单选4 同款)

第2题A. 3, 4

  • strlen=3(abc 三个字符,不含 \0);sizeof=4(含末尾 \0)

第3题A. 2

  • strcpy(s1,"Hi") 把 "Hi" 拷入并返回 s1 地址;strlen("Hi")=2(2024 填空2 同款)

第4题B. 错误

  • 二维数组按行优先存储(先存满一行再下一行),不是列优先

第5题:参考代码

c
#include <stdio.h>

int main() {
    int a[5], i, sum = 0;
    for (i = 0; i < 5; i++)
        scanf("%d", &a[i]);
    for (i = 0; i < 5; i++)
        sum += a[i];
    printf("和 = %d\n", sum);
    return 0;
}
  • 两个循环:读入 + 累加;注意 scanf&a[i]

📝 原有闭卷真题挑战(保留原内容 + 扩充)

(点击下方空白查看答案)

1. int a[3][4]; 共有几个元素?行下标范围?列下标范围?

2. char s[]="Hello"; sizeof(s)=___?  strlen(s)=___?

3. if(strcmp(s1,"abc")==0) 表示什么?

4. 二维数组定义时哪个维度的长度可以省略?

5. 写出输出:
   char s[10]="Hello";
   printf("%d", sizeof(s));

(扩充题)

6. int a[4] = {1, 2}; 写出 a[2]、a[3] 的值?

7. 写出输出:
   char s[] = "abc";
   printf("%d %d", strlen(s), sizeof(s));

8. 写出输出:
   char s1[10] = "Hello";
   char s2[] = "OK";
   printf("%d", strlen(strcpy(s1, s2)));
👆 点击展开答案
  1. 12个元素(3×4=12),行下标0~2,列下标0~3

  2. sizeof(s)=6(含\0),strlen(s)=5(不含\0)

  3. 表示 s1等于"abc"(strcmp相等返回0)

  4. 行数可以省略(编译器自动推断),列数不能省略

  5. 10(sizeof是数组占的总字节数,不是字符串长度)

  6. a[2]=0, a[3]=0(部分初始化自动补 0)

  7. 3 4(strlen=3 不含\0;sizeof=4 含\0)

  8. 2(strcpy 返回 s1 地址,strlen("OK")=2)


📖 教材习题对照

教材习题知识点难度
习题6.1~6.2一维数组定义与引用⭐⭐
习题6.4二维数组⭐⭐
习题6.5~6.6字符数组与字符串⭐⭐⭐
习题6.7字符串处理函数⭐⭐⭐

对应教材:谭浩强《C程序设计》第5版 → 第6章 利用数组处理批量数据 对应考试大纲:考点6 — 数组

📺 配套视频

复习到本考点 → 先看视频补讲,再刷上面「闭卷挑战」。

仅供个人学习 · 考生回忆版 · 非考试院原卷