C语言指针专题三 -- 指针数组

目录

1. 指针数组的核心原理

2. 指针数组与二维数组的区别

3. 编程实例

4. 常见陷阱与防御

5. 总结


1. 指针数组的核心原理

指针数组是一种特殊数组,其所有元素均为指针类型。每个元素存储一个内存地址,可指向不同类型的数据(通常指向同类型数据)。
核心特性

  1. 声明语法数据类型 *数组名[长度];

    • 例如:int *arr[5]; 表示一个包含5个int*类型指针的数组。

  2. 内存布局

    • 指针数组本身在内存中连续存储(存储的是指针值,即地址),但这些指针指向的实际数据可以是分散的。

  3. 典型应用

    • 管理多个字符串(如char *str_list[])。

    • 动态创建“锯齿状”二维数组(每行长度不同)。

    • 实现多级数据结构(如指向指针的指针数组)。

  4. 初始化与存储

            初始化方式与一般数组初始化相同,指针数组每个元素指向初始化内存区域。

int main()
{   
	int b[2][3];
	int *pb[2];
    //初始化方法一
	pb[0]=b[0];
	pb[1]=b[1];
    //初始化方法二
    //int b[2][3];
    //int *pb[ ]={b[0],b[1]};

	……

    return 0;
}

2. 指针数组与二维数组的区别

当使用指针数组处理二维数组时,其步长为二维数组行增长单元,如图所示

3. 编程实例

实例1:字符串指针数组(管理多个字符串)

#include <stdio.h>

int main() {
    // 声明并初始化字符串指针数组
    char *fruits[] = {"Apple", "Banana", "Cherry", "Date"};
    int count = sizeof(fruits) / sizeof(fruits[0]);

    // 遍历输出所有字符串
    for (int i = 0; i < count; i++) {
        printf("Fruit %d: %s\n", i + 1, fruits[i]);
    }

    return 0;
}

输出

Fruit 1: Apple
Fruit 2: Banana
Fruit 3: Cherry
Fruit 4: Date

 内存示意图

指针数组(栈内存)      只读内存区(字符串字面量)
+--------+         +-----------------+
| 0x1000 | ------> | 'A' 'p' 'p' ... | "Apple"
+--------+         +-----------------+
| 0x2000 | ------> | 'B' 'a' 'n' ... | "Banana"
+--------+         +-----------------+
| 0x3000 | ------> | 'C' 'h' 'e' ... | "Cherry"
+--------+         +-----------------+
| 0x4000 | ------> | 'D' 'a' 't' ... | "Date"
+--------+         +-----------------+

实例2:动态创建“锯齿状”二维数组

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

int main() {
    // 声明指针数组(3个int*类型指针)
    int *matrix[3];
    
    // 动态分配每行内存(每行长度不同)
    matrix[0] = (int*)malloc(2 * sizeof(int));  // 第0行2个元素
    matrix[1] = (int*)malloc(3 * sizeof(int));  // 第1行3个元素
    matrix[2] = (int*)malloc(1 * sizeof(int));  // 第2行1个元素

    // 初始化数据
    matrix[0][0] = 1; matrix[0][1] = 2;
    matrix[1][0] = 3; matrix[1][1] = 4; matrix[1][2] = 5;
    matrix[2][0] = 6;

    // 打印锯齿状数组
    for (int i = 0; i < 3; i++) {
        int cols = (i == 0) ? 2 : (i == 1) ? 3 : 1;
        for (int j = 0; j < cols; j++) {
            printf("matrix[%d][%d] = %d  ", i, j, matrix[i][j]);
        }
        printf("\n");
    }

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

输出

matrix[0][0] = 1  matrix[0][1] = 2  
matrix[1][0] = 3  matrix[1][1] = 4  matrix[1][2] = 5  
matrix[2][0] = 6  

 内存示意图

指针数组(栈内存)      堆内存(动态分配)
+--------+         +-----+-----+
| 0x5000 | ------> | 1   | 2   |  // 第0行
+--------+         +-----+-----+
| 0x6000 | ------> | 3   | 4   | 5  // 第1行
+--------+         +-----+-----+-----+
| 0x7000 | ------> | 6   |          // 第2行
+--------+         +-----+

实例3:多级指针数组(二维指针数组)

#include <stdio.h>

int main() {
    // 声明二维指针数组(3行,每行2个char*指针)
    char *names[3][2] = {
        {"Alice", "Bob"},
        {"Charlie", "David"},
        {"Eve", "Frank"}
    };

    // 遍历输出所有名字
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 2; j++) {
            printf("names[%d][%d]: %s\n", i, j, names[i][j]);
        }
    }
    return 0;
}

输出

names[0][0]: Alice
names[0][1]: Bob
names[1][0]: Charlie
names[1][1]: David
names[2][0]: Eve
names[2][1]: Frank

4. 常见陷阱与防御

1. 未初始化指针直接使用

int *arr[3];
printf("%d", arr[0][0]); // 错误!指针未指向有效内存

防御:确保指针指向合法内存后再访问。 

2. 内存泄漏

int *arr[3];
arr[0] = malloc(10 * sizeof(int));
// 忘记释放arr[0]

防御:动态分配的内存必须逐个释放。

3. 越界访问

char *strs[2] = {"Hello", "World"};
printf("%s", strs[2]); // 越界访问(有效索引为0和1)

防御:严格检查数组索引范围。

5. 总结

  • 指针数组通过存储多个指针实现灵活的数据管理,尤其适合处理字符串集合或动态二维数组。

  • 与二维数组相比,指针数组支持 各行长度不同 和 动态内存分配,但需手动管理内存。

  • 使用场景:

    • 管理多个字符串(如命令行参数char *argv[])。

    • 构建稀疏矩阵(部分行有数据,部分行为空)。

    • 实现复杂数据结构(如树、图的邻接表)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/962334.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot - 数据库集成06 - 集成ElasticSearch

Spring boot 集成 ElasticSearch 文章目录 Spring boot 集成 ElasticSearch一&#xff1a;前置工作1&#xff1a;项目搭建和依赖导入2&#xff1a;客户端连接相关构建3&#xff1a;实体类相关注解配置说明 二&#xff1a;客户端client相关操作说明1&#xff1a;检索流程1.1&…

深入理解MySQL 的 索引

索引是一种用来快速检索数据的一种结构, 索引使用的好不好关系到对应的数据库性能方面, 这篇文章我们就来详细的介绍一下数据库的索引。 1. 页面的大小: B 树索引是一种 Key-Value 结构&#xff0c;通过 Key 可以快速查找到对应的 Value。B 树索引由根页面&#xff08;Root&am…

vue之pinia组件的使用

1、搭建pinia环境 cnpm i pinia #安装pinia的组件 cnpm i nanoid #唯一id&#xff0c;相当于uuid cnpm install axios #网络请求组件 2、存储读取数据 存储数据 >> Count.ts文件import {defineStore} from piniaexport const useCountStore defineStore(count,{// a…

【MySQL — 数据库增删改查操作】深入解析MySQL的 Update 和 Delete 操作

1. 测试数据 mysql> select* from exam1; ----------------------------------------- | id | name | Chinese | Math | English | ----------------------------------------- | 1 | 唐三藏 | 67.0 | 98.0 | 56.0 | | 2 | 孙悟空 | 87.0 | 78.…

数据结构与算法之二叉树: LeetCode LCP 10. 二叉树任务调度 (Ts版)

二叉树任务调度 https://leetcode.cn/problems/er-cha-shu-ren-wu-diao-du/description/ 描述 任务调度优化是计算机性能优化的关键任务之一。在任务众多时&#xff0c;不同的调度策略可能会得到不同的总体执行时间&#xff0c;因此寻求一个最优的调度方案是非常有必要的 通…

JAVA 接口、抽象类的关系和用处 详细解析

接口 - Java教程 - 廖雪峰的官方网站 一个 抽象类 如果实现了一个接口&#xff0c;可以只选择实现接口中的 部分方法&#xff08;所有的方法都要有&#xff0c;可以一部分已经写具体&#xff0c;另一部分继续保留抽象&#xff09;&#xff0c;原因在于&#xff1a; 抽象类本身…

游戏引擎 Unity - Unity 启动(下载 Unity Editor、生成 Unity Personal Edition 许可证)

Unity Unity 首次发布于 2005 年&#xff0c;属于 Unity Technologies Unity 使用的开发技术有&#xff1a;C# Unity 的适用平台&#xff1a;PC、主机、移动设备、VR / AR、Web 等 Unity 的适用领域&#xff1a;开发中等画质中小型项目 Unity 适合初学者或需要快速上手的开…

【基于SprintBoot+Mybatis+Mysql】电脑商城项目之用户注册

&#x1f9f8;安清h&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;【计算机网络】【Mybatis篇】 &#x1f6a6;作者简介&#xff1a;一个有趣爱睡觉的intp&#xff0c;期待和更多人分享自己所学知识的真诚大学生。 目录 &#x1f3af;项目基本介绍 &#x1f6a6;项…

视频多模态模型——视频版ViT

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细解读多模态论文《ViViT: A Video Vision Transformer》&#xff0c;2021由google 提出用于视频处理的视觉 Transformer 模型&#xff0c;在视频多模态领域有…

DeepSeek本地部署(windows)

一、下载并安装Ollama 1.下载Ollama Ollama官网:Ollama 点击"Download",会跳转至下载页面。 点击"Download for Windows"。会跳转Github进行下载,如下载速度过慢,可在浏览器安装GitHub加速插件。 2.安装Ollama 双击下载的安装文件,点击"Inst…

1 HDFS

1 HDFS 1. HDFS概述2. HDFS架构3. HDFS的特性4. HDFS 的命令行使用5. hdfs的高级使用命令6. HDFS 的 block 块和副本机制6.1 抽象为block块的好处6.2 块缓存6.3 hdfs的文件权限验证6.4 hdfs的副本因子 7. HDFS 文件写入过程&#xff08;非常重要&#xff09;7.1 网络拓扑概念7.…

全国31省空间权重矩阵(地理相邻空间、公路铁路地理距离空间、经济空间)权重矩阵数据-社科数据

中国31个省份空间权重矩阵-社科数据https://download.csdn.net/download/paofuluolijiang/90028597 https://download.csdn.net/download/paofuluolijiang/90028597 空间权重矩阵是反映个体在空间中依赖关系的矩阵&#xff0c;本数据计算全国31个省三种标准化处理的空间权重矩…

Flask框架基础入门教程_ezflaskapp

pip install flaskFlask 快速入门小应用 学东西&#xff0c;得先知道我们用这个东西&#xff0c;能做出来一个什么东西。 一个最小的基于flask 的应用可能看上去像下面这个样子&#xff1a; from flask import Flask app Flask(__name__)app.route(/) def hello_world():ret…

机器学习笔记——特征工程

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本笔记介绍机器学习中常见的特征工程方法、正则化方法和简要介绍强化学习。 文章目录 特征工程&#xff08;Fzeature Engineering&#xff09;1. 特征提取&#xff…

Cursor火出圈,未来程序员还有出路吗?

大家好&#xff0c;我是凡人。 今天我表弟家邻居的阿姨&#xff0c;托他问问我目前程序员还有前景吗&#xff0c;希望我根据十几年的经验给出点建议&#xff0c;看看程序员这条路未来能不能走。 一下子不知道该怎么回复他了&#xff0c;如果是三年前问我&#xff0c;肯定毫不…

如何移植ftp服务器到arm板子?

很多厂家提供的sdk&#xff0c;一般都不自带ftp服务器功能&#xff0c; 需要要发人员自己移植ftp服务器程序。 本文手把手教大家如何移植ftp server到arm板子。 环境 sdk&#xff1a;复旦微 Buildroot 2018.02.31. 解压 $ mkdir ~/vsftpd $ cp vsftpd-3.0.2.tar.gz ~/vs…

第5章 公共事件

HarmonyOS通过公共事件服务为应用程序提供订阅、发布、退订公共事件的能力。 5.1 公共事件概述 在应用里面&#xff0c;往往会有事件。比如&#xff0c;朋友给我手机发了一条信息&#xff0c;未读信息会在手机的通知栏给出提示。 5.1.1 公共事件的分类 公共事件&#xff08…

STM32 对射式红外传感器配置

这次用的是STM32F103的开发板&#xff08;这里面的exti.c文件没有how to use this driver 配置说明&#xff09; 对射式红外传感器 由一个红外发光二极管和NPN光电三极管组成&#xff0c;M3固定安装孔&#xff0c;有输出状态指示灯&#xff0c;输出高电平灯灭&#xff0c;输出…

【数据结构】(2)时间、空间复杂度

一、衡量算法好坏的指标 时间复杂度衡量算法的运行速度&#xff0c;空间复杂度衡量算法所需的额外空间。这些指标&#xff0c;是某场景中选择使用哪种数据结构和算法的依据。如今&#xff0c;计算机的存储器已经变得容易获得&#xff0c;所以不再太关注空间复杂度。 二、渐进表…

FBX SDK的使用:基础知识

Windows环境配置 FBX SDK安装后&#xff0c;目录下有三个文件夹&#xff1a; include 头文件lib 编译的二进制库&#xff0c;根据你项目的配置去包含相应的库samples 官方使用案列 动态链接 libfbxsdk.dll, libfbxsdk.lib是动态库&#xff0c;需要在配置属性->C/C->预…