Skip to content

C 数组

数组(array)是 C 语言中一种基本数据结构(data structure),用于存储固定大小、顺序排列的**相同数据类型(same data type)**元素集合。可以将其视为同一类型的变量组,它们在内存中连续(contiguously)存储(一个接一个),可以通过一个公共名称和索引(index)进行访问。

与其声明诸如 score1, score2, score3, … 的单独变量,不如声明一个名为 scores 的数组变量,并使用索引访问各个元素:scores[0], scores[1], scores[2], …。

关键特性:

  • 固定大小(Fixed Size): 标准 C 数组的大小必须在编译时确定,不能在运行时(runtime)改变。(C99 引入了可变长数组(Variable Length Arrays, VLAs),但其使用有局限性和潜在风险)。
  • 同质元素(Homogeneous Elements): 数组内的所有元素必须具有相同的数据类型(例如,全部是 int,全部是 float,全部是 char)。
  • 连续内存(Contiguous Memory): 数组元素存储在相邻的内存位置,这使得访问效率很高。
  • 基于零的索引(Zero-Based Indexing): 第一个元素使用索引 0 访问,第二个使用索引 1,大小为 N 的数组的最后一个元素使用索引 N-1 访问。

要声明数组,你需要指定元素类型(element type)、数组名(array name)和包含在方括号 [] 中的元素数量(大小,size):

type arrayName[arraySize];

arraySize 必须是大于零的整数常量表达式。type 可以是任何有效的 C 数据类型(data type)。

示例:

#define MAX_STUDENTS 50
// Declare an array of 10 integers
int counters[10];
// Declare an array of 20 floating-point numbers
float temperatures[20];
// Declare an array to hold grades for MAX_STUDENTS
char grades[MAX_STUDENTS];

数组可以在声明时使用包含在花括号 {} 中的初始化列表(initializer list)进行初始化:

// Initialize an array of 5 doubles
double balances[5] = { 1000.0, 2.0, 3.4, 7.0, 50.0 };
// Initialize an array of integers
int sequence[6] = { 1, 1, 2, 3, 5, 8 };

重要的初始化规则:

  • {} 中的初始化器数量不能超过声明的数组大小。
  • 部分初始化(Partial Initialization): 如果提供的初始化器数量少于数组大小,剩余的元素将自动初始化为零(对于算术类型(arithmetic types))或 NULL(对于指针(pointers))。
  • 省略大小(Omitting Size): 如果提供了初始化列表但省略了数组大小,编译器会根据初始化器的数量自动确定大小。
// Partial initialization: first 3 elements initialized, last 7 are zero.
int partial[10] = { 5, 10, 15 };
// Omitting size: compiler creates an array of size 4.
char vowels[] = { 'a', 'e', 'i', 'o', 'u' }; // Size is 5
// String literal initialization (includes null terminator)
char message[] = "Hello"; // Size is 6 ('H','e','l','l','o','\0')
// 字符串字面量初始化(包含空终止符)

单个数组元素使用数组名后跟方括号 [] 中的元素索引(index)来访问。

记住:第一个元素的索引是 0,最后一个元素的索引是 arraySize - 1。

示例:

int values[5] = { 10, 20, 30, 40, 50 };
int firstValue = values[0]; // Access first element (value is 10)
int thirdValue = values[2]; // Access third element (value is 30)
values[4] = 99; // Modify the last element (index 4)
// Attempting to access values[5] would be an error (out of bounds)

重要警告: C 语言不对数组访问执行自动边界检查(bounds checking)。访问超出有效索引范围的元素(例如,array[-1] 或 array[arraySize])会导致未定义行为(undefined behavior)。这可能导致程序崩溃(crashes)、数据损坏(corrupt data)或引发严重的安全漏洞(security vulnerabilities)(缓冲区溢出,buffer overflows)。程序员(programmer)有责任确保所有数组访问都在有效边界内。

#include <stdio.h>
#include <stddef.h> // For size_t
#define ARRAY_SIZE 10
int main(void) {
int numbers[ARRAY_SIZE]; // 声明一个包含 10 个整数的数组
size_t i; // 使用 size_t 表示数组索引/大小 - 这是标准做法
// 使用循环初始化元素
printf("Initializing array...\n");
for (i = 0; i < ARRAY_SIZE; ++i) {
numbers[i] = (int)(i * i); // 存储平方值:0, 1, 4, 9...
}
// 访问并打印每个元素的值
printf("\nArray elements:\n");
for (i = 0; i < ARRAY_SIZE; ++i) {
// 防御性检查(可选,但在复杂场景中是良好实践)
if (i < ARRAY_SIZE) {
printf("Element[%zu] = %d\n", i, numbers[i]);
} else {
printf("Error: Index %zu out of bounds!\n", i);
// 适当处理错误
}
}
return 0;
}

编译并执行后,输出如下:

Initializing array...
Array elements:
Element[0] = 0
Element[1] = 1
Element[2] = 4
Element[3] = 9
Element[4] = 16
Element[5] = 25
Element[6] = 36
Element[7] = 49
Element[8] = 64
Element[9] = 81

数组是一个基础主题,还有更高级的方面:

概念描述
Multi-dimensional arrays数组的数组,用于表示表格或矩阵(例如,int matrix[3][4];)。
Passing arrays to functions当数组名传递给函数时,它会“衰退”为指向其第一个元素的指针。除非单独传递,否则大小信息会丢失。
Returning arrays from functions函数不能直接返回整个数组。常用技术包括返回指向动态分配数组的指针,返回指向静态数组的指针(谨慎使用),或将数组封装在结构体(struct)中。
Pointers and Arrays指针和数组在 C 语言中有很强的关联性。数组名本身在很多上下文中表现得像指向第一个元素的指针(例如,arrayName 等同于 &arrayName[0])。
Variable Length Arrays (VLAs)C99 引入,允许数组大小在运行时(runtime)确定。声明方式类似 int arr[n];,其中 n 是变量。在 C11/C17/C23 中变为可选特性。如果 n 很大,可能存在栈溢出(stack overflow)风险。谨慎使用;动态分配(malloc)对于运行时大小的数组通常更安全。

这些主题通常会在后续章节或教程中更详细地介绍。