👇😊 C语言数组 😊👇


🌈 1. 数组是什么?

想象你有一排储物柜🔒,每个柜子编号从0开始,存放同类型物品(比如全是书包)。这就是数组!

  • 作用:一次性管理多个同类数据,避免定义一堆变量!
  • 特点连续内存存储,快速访问任意元素!

🌈 2. 数组的声明与初始化

2.1 声明数组

📝 语法数据类型 数组名[元素个数];

1
2
int scores[5];      // 声明能存5个整数的数组
double prices[10]; // 声明能存10个双精度数的数组

⚠️ 错误示例

1
2
int size = 5;
int arr[size]; // ❌ 错误!数组大小必须是常量(C99前)

2.2 初始化数组

  • 完全初始化:指定所有元素
    1
    int nums[3] = {10, 20, 30}; // nums[0]=10, nums[1]=20, nums[2]=30
  • 部分初始化:剩余元素自动补0
    1
    int arr[5] = {1, 2}; // arr = [1,2,0,0,0]
  • 自动计算大小:省略元素个数
    1
    char letters[] = {'A', 'B', 'C'}; // 自动识别长度为3

⚠️ 错误示例

1
int a[3] = {1,2,3,4}; // ❌ 初始值太多!

🌈 3. 访问数组元素

  • 索引从0开始!最后一个元素索引是长度-1
    1
    2
    3
    int nums[3] = {10, 20, 30};
    printf("%d", nums[0]); // 输出10
    nums[2] = 40; // 修改第三个元素为40

💥 致命错误:数组越界!

1
2
int arr[5] = {0};
arr[5] = 10; // ❌ 有效索引是0-4,越界可能导致程序崩溃!

🌈 4. 获取数组长度

使用 sizeof 计算总大小除以单个元素大小:

1
2
int arr[] = {1,2,3,4,5};
int length = sizeof(arr) / sizeof(arr[0]); // 5

🔧 进阶技巧:用宏定义简化

1
2
#define LEN(arr) (sizeof(arr)/sizeof(arr[0]))
int len = LEN(arr); // 直接调用

⚠️ 注意在函数中传递数组时,无法用此法获取长度(数组退化为指针)!

1
2
3
void printArray(int arr[]) {
// sizeof(arr) 这里得到的是指针大小,不是数组大小!
}

🌈 5. 数组名与指针的关系

  • 数组名是首元素地址的常量指针(不能修改指向)

    1
    2
    3
    int arr[3] = {10, 20, 30};
    int *ptr = arr; // 等价于 ptr = &arr[0]
    printf("%d", *ptr); // 输出10
  • 用指针遍历数组

    1
    2
    3
    for(int i=0; i<5; i++) {
    printf("%d ", *(ptr + i)); // 访问arr[i]
    }

⚠️ 易混淆点

1
2
3
4
int arr[5];
int *p = arr;
// arr++; // ❌ 数组名是常量,不能修改!
p++; // ✅ 指针可以移动

🌈 6. 数组作为函数参数

传递数组给函数时,实际传递的是指针(首地址),函数内可修改原数组!

1
2
3
4
5
6
7
8
9
10
11
12
// 函数定义
void doubleValues(int *arr, int len) {
for(int i=0; i<len; i++) {
arr[i] *= 2; // 修改原数组元素
}
}

int main() {
int nums[] = {1,2,3};
doubleValues(nums, 3); // 传递数组名和长度
// nums变成[2,4,6]
}

🌈 7. 多维数组(以二维为例)

7.1 声明与初始化

二维数组类似表格📊,有行和列:

1
2
3
4
int matrix[2][3] = {
{1,2,3}, // 第0行
{4,5,6} // 第1行
};

7.2 访问元素

1
printf("%d", matrix[1][2]); // 输出6(第1行第2列)

后续的话会单独用一篇文章来讲解二维数组!!!😏

🌈 8. 静态数组 vs 动态数组

类型 特点 示例
静态数组 编译时确定大小,内存自动分配/释放 int arr[10];
动态数组 运行时手动分配(malloc),需手动释放 int *arr = malloc(n * sizeof(int));

🌰 动态数组示例

1
2
3
4
5
6
7
8
int n = 5;
int *arr = (int*)malloc(n * sizeof(int)); // 申请内存
if(arr != NULL) {
for(int i=0; i<n; i++) {
arr[i] = i+1; // 初始化
}
free(arr); // 释放内存!
}

❌ 9. 常见错误集锦

  1. 越界访问:索引超出范围 → 程序崩溃
  2. 未初始化就使用:局部数组元素是随机值
  3. 在函数中用sizeof求长度:得到指针大小而非数组长度
  4. 修改数组名:数组名是常量指针,不能arr++

🌈 10. 综合练习

练习1:求数组最大值

写一个函数 int findMax(int arr[], int len),返回数组中的最大值。

练习2:反转数组

写一个函数 void reverse(int arr[], int len),将数组元素原地反转。

练习3:错误修复

以下代码有什么问题?

1
2
3
4
5
int main() {
int arr[3] = {1,2,3};
printf("%d", arr[3]); // 输出第4个元素?
return 0;
}

🎯 参考答案

练习1

1
2
3
4
5
6
7
int findMax(int arr[], int len) {
int max = arr[0];
for(int i=1; i<len; i++) {
if(arr[i] > max) max = arr[i];
}
return max;
}

练习2

1
2
3
4
5
6
7
void reverse(int arr[], int len) {
for(int i=0; i<len/2; i++) {
int temp = arr[i];
arr[i] = arr[len-1-i];
arr[len-1-i] = temp;
}
}

练习3

错误arr[3] 越界访问(有效索引为0-2)
修正printf("%d", arr[2]);


🚀 总结:数组是C语言的“数据集装箱”,掌握索引、内存布局和指针操作是关键!多练习,多调试,轻松玩转数组!