当前位置: 首页 > news >正文

C语言数组知识点

一、数组的基本概念

     1.定义

数组是相同数据类型元素的集合,通过连续内存存储,支持高效访问。

核心特点

  • 元素类型相同

  • 内存连续分配

  • 通过下标访问(从 0 开始)

      2.分类

  • 一维数组:线性结构(如 int arr[5]
  • 多维数组:嵌套结构(如二维数组 int arr[3][4]


二、一维数组

     1.声明与初始化

     声明格式数据类型 数组名[元素个数];

int arr[5];          // 声明未初始化(局部变量元素值为随机数)  
static int s_arr[3]; // 静态数组未初始化元素默认为0  
  • 初始化方式

    初始化类型示例代码说明
    完全初始化int arr[3] = {1, 2, 3};所有元素显式赋值
    部分初始化int arr[5] = {1, 2};剩余元素自动补0(仅全局/静态数组有效)
    长度自动推断int arr[] = {10, 20, 30};等价于 arr[3]
    2.内存特性

           连续存储:相邻元素地址差为 sizeof(元素类型)

int arr[3] = {1, 2, 3};  
printf("地址差:%td\n", (char*)&arr[1] - (char*)&arr[0]); // 输出:4(假设int占4字节)  
  • 越界风险:C语言不检查数组边界,越界访问可能导致程序崩溃或数据污染。

    int arr[3] = {1};  
    arr[3] = 100; // 危险操作!覆盖未知内存区域  

    3.数组名与指针关系

      数组名本质:数组名在大多数场景下退化为指向首元素的指针

int arr[5] = {0};  
int *p = arr;          // 合法,p指向arr[0]  
int (*p_arr)[5] = &arr; // 数组指针类型  

例外情况

  • sizeof(arr):返回整个数组的字节大小(如 int[5] 返回 20

  • &arr:返回指向整个数组的指针(类型为 int(*)[5]


三、二维数组
  1. 声明与初始化

        声明格式数据类型 数组名[行数][列数];

int matrix[3][4]; // 3行4列的二维数组  
  • 初始化方式

    初始化类型示例代码说明
    完全初始化(分行)int m[2][3] = {{1,2,3}, {4,5,6}};每行显式赋值
    连续初始化int m[2][3] = {1,2,3,4,5,6};按行优先顺序填充
    部分初始化int m[3][4] = {{1}, {0,5}, [2]={9,8}};C99支持指定行初始化
    2.内存布局

行优先存储:二维数组本质是一维数组的嵌套,内存按行连续分配。

int arr[2][3] = {{1,2,3}, {4,5,6}};  
// 内存地址验证  
printf("行间地址差:%td\n", (char*)&arr[1][0] - (char*)&arr[0][0]); // 输出:12(假设int为4字节)  

多维数组的指针视角

二维数组名退化为指向第一行(子数组)的指针:

int arr[2][3];  
int (*p_row)[3] = arr; // p_row指向第一行(类型为int(*)[3]) 

四、动态数组

1.动态内存分配

使用 malloccallocrealloc 和 free 实现动态数组:

// 动态创建数组  
int *dyn_arr = (int*)malloc(10 * sizeof(int));  
if (dyn_arr == NULL) {  
    perror("内存分配失败");  
    exit(EXIT_FAILURE);  
}  

// 扩容数组(从10元素扩展到20)  
int *temp = (int*)realloc(dyn_arr, 20 * sizeof(int));  
if (temp != NULL) {  
    dyn_arr = temp;  
} else {  
    free(dyn_arr); // 扩容失败需释放原内存  
}  

// 释放内存  
free(dyn_arr);  

2.变长数组(VLA)

  • C99标准支持:数组长度在运行时确定(部分编译器可能不支持)。

    
    void func(int n) {  
        int vla[n]; // 变长数组  
        // ...  
    } // 生命周期结束后自动释放  


五、数组的常见用法

1.遍历数组

  • 一维数组遍历:

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

  • 二维数组遍历:

    int matrix[3][4] = {0};  
    for (int i=0; i<3; i++) {  
        for (int j=0; j<4; j++) {  
            matrix[i][j] = i + j;  
        }  
    }  

2.数组作为函数参数

  • 传递方式:数组名退化为指针,需额外传递长度信息。

    // 一维数组作为参数  
    void printArray(int arr[], int len) { // 等价于int *arr  
        for (int i=0; i<len; i++) {  
            printf("%d ", arr[i]);  
        }  
    }  
    
    // 二维数组作为参数(需指定列数)  
    void printMatrix(int mat[][4], int rows) {  
        for (int i=0; i<rows; i++) {  
            for (int j=0; j<4; j++) {  
                printf("%d ", mat[i][j]);  
            }  
        }  
    }  


六、注意事项与常见错误

1.常见错误

  • 越界访问:导致未定义行为(崩溃或数据损坏)

    
    int arr[3] = {1,2,3};  
    arr[3] = 4; // 错误!越界访问  

  • 未初始化的局部数组:元素值为随机数

    int arr[5];  
    printf("%d", arr[0]); // 输出不确定的值  

2.数组与指针的陷阱

  • 数组名不可修改

    int arr[5] = {0};  
    arr++; // 错误!数组名不是左值  

  • 指针与数组长度计算

    int arr[5];  
    int *p = arr;  
    printf("数组长度错误计算:%zu\n", sizeof(p)/sizeof(int)); // 输出:1或2(指针大小)  


七、代码示例:数组综合应用

#include <stdio.h>  
#include <stdlib.h>  

// 动态创建并操作二维数组  
void dynamicMatrixDemo() {  
    int rows = 3, cols = 4;  
    // 动态分配内存  
    int **matrix = (int**)malloc(rows * sizeof(int*));  
    for (int i=0; i<rows; i++) {  
        matrix[i] = (int*)malloc(cols * sizeof(int));  
    }  

    // 赋值与打印  
    for (int i=0; i<rows; i++) {  
        for (int j=0; j<cols; j++) {  
            matrix[i][j] = i * cols + j;  
            printf("%2d ", matrix[i][j]);  
        }  
        printf("\n");  
    }  

    // 释放内存  
    for (int i=0; i<rows; i++) {  
        free(matrix[i]);  
    }  
    free(matrix);  
}  

int main() {  
    dynamicMatrixDemo();  
    return 0;  
}  

总结

核心原则:数组是C语言中连续内存块的直接体现,需手动管理内存与边界。

关键区别

  • 静态数组(编译时确定大小) vs 动态数组(运行时分配)

  • 一维数组(线性访问) vs 多维数组(嵌套结构)

安全实践

  • 始终检查数组边界

  • 动态内存分配后验证指针有效性

  • 使用 sizeof(arr)/sizeof(arr[0]) 计算静态数组长度

通过掌握数组的内存布局、指针关系及动态管理,可高效处理批量数据,同时避免常见陷阱。

http://www.dtcms.com/a/107433.html

相关文章:

  • 【C语言】深入理解指针(四):回调函数与qsort函数的奥秘
  • Mysql MIC高可用集群搭建
  • python的一些使用姿势
  • 【HTML】分享一个自己写的3*3拼图小游戏
  • Go语言从零构建SQL数据库(4)-解析器
  • 人工智能之数学基础:矩阵分解之LU分解
  • Stable Diffusion win10 Cpu安装日志
  • 国产三维CAD「皇冠CAD」在汽车零部件领域建模教程:刹车片
  • React-Diffing算法和key的作用
  • 【AI论文】什么、如何、何处以及效果如何?大语言模型测试时缩放技术调研
  • Python扩展知识详解:map函数
  • Pinia持久化插件pinia-plugin-persistedstate
  • Ubuntu安装psql
  • 推导Bias² + Variance + σ²_ε
  • Java项目之基于ssm的校园驿站管理系统(源码+文档)
  • GO语言学习(16)Gin后端框架
  • Linux服务器环境下如何优化环境变量
  • DeepSeek 开源的 3FS 如何?
  • 【Pandas】pandas DataFrame info
  • 高速电路中的PCB及其完整性设计
  • AI的未来演进
  • ubuntu git cola gui
  • DecodeEX 功能揭秘:什么是“复制交易”?
  • Windows 10 如何设置右击鼠标快速进行“关机”
  • Java安全 - CC1链
  • 基于Spring Boot的社区互助平台的设计与实现(LW+源码+讲解)
  • 如何批量将带有GPS信息的照片导入奥维地图:完整指南
  • 园门打印机配置教程
  • 网络安全与防护策略
  • 基于Spring Boot的实验室课程管理系统的设计与实现(LW+源码+讲解)