• 0
  • 0
  • 0
  • C语言数组概念以及使用方法

  • 小小baby
  • 4,369
  • 2026-06-24 20:10
  • 数组是C语言中最核心的数据结构之一,几乎所有复杂程序都离不开它。本文将从最基础的概念出发,逐步深入到内存模型、指针关系、多维数组、字符串处理以及常见算法实践,构建一个完整且系统的数组知识体系。

    1. 什么是数组

    数组是一个连续的内存空间,用于存储相同数据类型的多个元素。
    定义一个数组的语法为:

    数据类型 数组名[长度];

    例如:

    int array[3];   // 可以存放3个整数的数组

    数组有两大特点:

    • 连续性:所有元素在内存中紧密排列,不是零散存放。
    • 定长性:数组一旦定义,其长度就无法改变(后面会解释“灵活理解”的部分)。
    补充理解:虽然数组长度固定,但C语言允许隐式类型转换。例如,你可以把一个 int 存入 double 类型的数组(取值范围小的类型可以安全地存入取值范围大的类型),这并不违反数组的同类型要求,因为存储时会自动转换为 double。

    2. 数组的初始化

    在定义数组时可以直接赋予初值,格式为用花括号 {} 包裹的值列表。

    完全初始化

    int arr[5] = {1, 2, 3, 4, 5};   // 5个元素全部指定

    部分初始化

    如果给出的值少于数组长度,剩余元素会被自动初始化为默认值:

    • 整数类型:0
    • 浮点类型:0.0
    • 字符类型:'\0'
    • 指针类型:NULL
    int arr[5] = {1, 2};  
    // arr[0]=1, arr[1]=2, arr[2]=0, arr[3]=0, arr[4]=0

    省略长度初始化

    当初始化列表已给出全部值时,可以省略长度,编译器会自动计算元素个数:

    int arr[] = {10, 20, 30, 40};  // 长度为4
    注意:如果长度省略但值列表个数为0(如 int arr[] = {};)是非法的,数组必须至少有一个元素。

    3. 元素的访问与修改

    数组使用下标(索引)访问元素,索引从 0 开始,到 长度-1 结束。

    int arr[5] = {10, 20, 30, 40, 50};
    
    int a = arr[0];      // 读取第1个元素:10
    int b = arr[2];      // 读取第3个元素:30
    
    arr[3] = 100;        // 将第4个元素修改为100

    遍历数组通常使用循环,这是处理批量数据的基石:

    int len = sizeof(arr) / sizeof(arr[0]);  // 计算元素个数
    for (int i = 0; i < len; i++) {
        printf("%d\n", arr[i]);
    }

    4. 数组的内存原理

    程序运行时,操作系统会为其分配内存,内存以字节为单位编址。数组占据一块连续的内存区域。

    • 数组名 arr 代表首元素的地址(即 &arr[0])。
    • 下标访问 arr[i] 本质上是从首地址开始,向后偏移 i × 数据类型大小 个字节。
    • 例如在64位系统中,int 类型占4字节:int arr[4] = {1, 2, 3, 4}; printf("%p\n", &arr[0]); // 首地址 printf("%p\n", &arr[1]); // 首地址 + 4 printf("%p\n", &arr[2]); // 首地址 + 8打印出的地址值会依次递增4,验证了连续性和偏移规律。
    使用 %p 格式符打印地址时,不要忘记对数组元素使用取地址符 &。

    5. 两个极易犯错的“坑”

    坑一:数组作为函数参数会退化为指针

    当数组作为函数实参传递时,传递的只是首地址(指针),而不是整个数组。

    void PrintArray(int arr[], int len) {
        // 在函数内部,sizeof(arr) 得到的是指针的大小(4或8字节)
        // 而不是整个数组的大小!
        for (int i = 0; i < len; i++) {
            printf("%d ", arr[i]);
        }
    }

    因此,必须额外传递数组的长度,函数才能正确遍历。
    在主调函数中计算长度的方法:

    int arr[] = {1, 2, 3, 4, 5};
    int len = sizeof(arr) / sizeof(arr[0]);  // 此处可以正确求出个数
    PrintArray(arr, len);

    坑二:数组索引越界

    C语言不会检查数组下标是否越界,访问非法内存会导致未定义行为(程序崩溃、数据被破坏等)。

    • 最大合法索引:长度 - 1
    • 最小合法索引:0
    int arr[3] = {1, 2, 3};
    printf("%d\n", arr[5]);  // 越界!危险!

    务必保证循环变量和手动索引始终在合法范围内。

    6. 实战案例

    案例一:寻找数组中的最大值

    遍历数组,用一个变量记录当前最大值,初始化为首元素(避免数组全为负数时出错)。

    int arr[] = {10, 20, 30, 40, 50, 60, 102};
    int max = arr[0];
    int len = sizeof(arr) / sizeof(arr[0]);
    
    for (int i = 1; i < len; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    printf("最大值:%d\n", max);

    案例二:生成随机数并求和

    利用 <stdlib.h> 的 rand() 和 <time.h> 的 time() 生成随机数,存入数组并计算总和。

    srand(time(NULL));               // 以当前时间为种子,确保每次运行随机数不同
    int array[10] = {0};
    int sum = 0;
    int len = sizeof(array) / sizeof(array[0]);
    
    // 生成10个 1~100 的随机数
    for (int i = 0; i < len; i++) {
        array[i] = rand() % 100 + 1;  //生成1 ~ 100范围内的随机数
    }
    
    // 求和
    for (int i = 0; i < len; i++) {
        printf("%d ", array[i]);
        sum += array[i];
    }
    printf("\n总和:%d\n", sum);

    7. 总结

    • 数组是同类型数据的连续集合,长度固定,通过下标访问。
    • 初始化时可省略长度,未显式赋值的元素具有类型对应的默认值。
    • 数组名代表首地址,下标运算等价于指针偏移。
    • 传递数组给函数时必须同时传递长度,避免因退化为指针而丢失大小信息。
    • 严防索引越界,所有循环和访问都要限定在 0 ~ length-1 之间。

    1. 什么是内存?

    软件在运行时,用来临时存储数据的

    操作系统会把内存按照字节划分为N多的小格子

    2. 什么是内存地址?

    概念:在内存中申请空间的编号

    32位操作系统:以32位的二进制表示

    64位操作系统:以64位的二进制表示

    书写的时候:转成十六进制方便阅读

    3. 内存地址的作用?

    快速的操作内存中的数据

    4. C语言中如何获取内存地址?

    &变量名

    5. 数组内存地址

    是第一个元素的第一个字节空间的地址,也是首地址

    索引:偏移量

    评论

  • 0
    /1000
    最热
  • 最新

    确认跳转

    您即将离开当前页面,访问外部链接。请注意核对网址,保护隐私安全。

    https://example.com

    言心安全助手 · 建议确认来源可信

    • 0
    • 0
    • 0
    登录后参与评论