一、数组的基本概念
-
定义:数组是相同类型数据元素的集合,这些元素在内存中连续存储
-
特点:
-
所有元素具有相同的数据类型
-
元素在内存中是连续存储的
-
通过下标(索引)访问元素,下标从0开始
-
二、一维数组的声明和初始化
1. 数组声明
数据类型 数组名[数组长度];
示例:
int numbers[5]; // 声明一个包含5个整数的数组
float scores[10]; // 声明一个包含10个浮点数的数组
char letters[26]; // 声明一个包含26个字符的数组
2. 数组初始化
(1) 完全初始化:
int numbers[5] = {1, 2, 3, 4, 5};
(2) 部分初始化(未初始化的元素自动设为0):
int numbers[5] = {1, 2}; // 等价于 {1, 2, 0, 0, 0}
(3) 不指定长度初始化(编译器自动计算长度):
int numbers[] = {1, 2, 3, 4, 5}; // 数组长度为5
(4) C99新增的指定初始化方式:
int numbers[5] = {[2] = 3, [4] = 5}; // 其他元素为0
强调:指针字节数与指针指向类型无关
16位系统:16 / 8 = 2字节;32位系统:32 / 8 = 4字节;64 / 8 = 8字节
三、数组元素的访问
-
通过下标访问:
int numbers[5] = {10, 20, 30, 40, 50}; int x = numbers[0]; // 访问第一个元素,x=10 numbers[2] = 100; // 修改第三个元素为100
-
数组下标范围是0到(数组长度-1),越界访问是未定义行为
四、数组在内存中的存储
-
数组元素在内存中是连续存储的
-
数组名代表数组首元素的地址
-
计算数组大小:
int numbers[5]; size_t size = sizeof(numbers); // 整个数组的字节大小 size_t element_count = sizeof(numbers) / sizeof(numbers[0]); // 元素个数
五、数组与指针的关系
-
数组名在大多数情况下会转换为指向其首元素的指针
-
指针可以像数组一样使用下标:
int numbers[5] = {1, 2, 3, 4, 5}; int *ptr = numbers; printf("%d", ptr[2]); // 输出3
-
数组名不是指针的例外情况:
-
使用sizeof运算符时
-
使用&运算符时
-
作为字符串字面量初始化字符数组时
-
六、数组作为函数参数
-
数组作为函数参数时,实际上传递的是数组首元素的地址
-
常用传递方式:
// 方式1:使用数组形式声明参数 void func(int arr[], int size); // 方式2:使用指针形式声明参数 void func(int *arr, int size);
-
调用示例:
int numbers[5] = {1, 2, 3, 4, 5}; func(numbers, 5);
七、常见数组操作
1. 遍历数组
int numbers[5] = {1, 2, 3, 4, 5};
for(int i = 0; i < 5; i++) {
printf("%d ", numbers[i]);
}
2. 数组赋值
int src[5] = {1, 2, 3, 4, 5};
int dest[5];
// 必须逐个元素赋值
for(int i = 0; i < 5; i++) {
dest[i] = src[i];
}
3. 查找元素
int findValue(int arr[], int size, int value) {
for(int i = 0; i < size; i++) {
if(arr[i] == value) {
return i; // 返回下标
}
}
return -1; // 未找到
}
4. 排序数组(冒泡排序示例)
void bubbleSort(int arr[], int size) {
for(int i = 0; i < size-1; i++) {
for(int j = 0; j < size-i-1; j++) {
if(arr[j] > arr[j+1]) {
// 交换
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
八、注意
-
数组越界:C语言不检查数组下标是否越界,越界访问可能导致程序崩溃或不可预测行为
-
数组长度:数组长度必须是编译时常量(C99之前)或常量表达式
-
数组名不可修改:数组名不是左值,不能赋值
-
数组大小固定:声明后大小不能改变
-
数组与指针的区别:
-
sizeof(数组名)返回整个数组的大小
-
sizeof(指针)返回指针本身的大小
-
&数组名得到的是指向整个数组的指针
-
指针可以重新赋值,数组名不能
-
九、C99新增特性
-
变长数组(VLA):
int n = 10; int arr[n]; // C99支持,但C11改为可选特性
-
指定初始化器:
int arr[10] = {[3] = 100, [7] = 200};
十、应用示例
#include <stdio.h>
#define SIZE 5
// 函数原型
void printArray(int arr[], int size);
double getAverage(int arr[], int size);
int main() {
// 初始化数组
int numbers[SIZE] = {10, 20, 30, 40, 50};
// 打印数组
printf("数组元素: ");
printArray(numbers, SIZE);
// 计算平均值
double avg = getAverage(numbers, SIZE);
printf("平均值: %.2f\n", avg);
return 0;
}
// 打印数组函数
void printArray(int arr[], int size) {
for(int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// 计算平均值函数
double getAverage(int arr[], int size) {
double sum = 0;
for(int i = 0