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

C语言-指针[指针数组和数组指针]

知识重复

  • 变量指针:变量最小的地址值(首地址),本质是地址、指针

  • 指针变量:存储指针的变量,本质是变量

  • &:取地址运算符(取址符、取地址符),获取变量、数组等的地址

  • *:指针操作符,如果这个符号前面有数据类型,就被称为“指针声明符”,如果没有数据类型,就被称为“解引用符”

  • 指向:指针变量存储了谁的地址,这个指针变量就指向了谁

  • 交换指向:指向发生改变,指向对象的数据不会改变

  • 交换数据:指向不发生改变,指向对象的数据会改变

  • 指针变量本质上还是变量,只不过指针变量只能存储其他内存单元的地址,我们借助于指针变量,就能实现内存空间的共享

  • 共享他人空间:

    int a = 10;
    int *p = &a;
    int *q = p;
    
  • 共享自己的空间:

    int a  = 10;
    int *p = &a;  //a和p共享a的空间
    

指针数组和数组指针

数组指针

定义
  • 概念:数组指针是指向数组的指针(指针变量),本质上还是指针

指针变量指向数组元素和数组指针的区别:
在这里插入图片描述

特点

  • ①先有数组,再有指针
  • ②它指向的是一个完整的数组

一维数组指针

语法

数据类型 (*指针变量名)[容量];

案例

在这里插入图片描述

我们之前所学的是指向数组元素的指针,本质上是指针变量;现在我们学的是指向数组的指针,叫做数组指针

二维数组指针

语法:

数据类型 (*指针变量名)[行容量][列容量];

案例1

//写法1:二维数组指针指向二维数组----不推荐
#include <stdio.h>
int main()
{//创建一个二维数组int arr[][3] = {10,20,30,100,200,300,1000,2000,3000};//定义一个二维数组指针指向二维数组int (*p)[][3] = &arr;//遍历数组for(int i = 0;i < 3; i++){for(int j = 0;j < 3; j++){printf("%-6d",(*p)[i][j]);}}printf("\n");//写法2:一维数组指针指向二维数组-----推荐//创建一个二维数组int arr[][3] = {10,20,30,100,200,300,1000,2000,3000};    //定义一个一维数组指针指向二维数组,相当于指针指向的是二维数组的行[行容量]int (*p)[3] = arr;//等价于&arr[0] (*p):指向数组的行   int arr[] = {100,200,300};  int *p = arr;  解引用p得到第一个元素//遍历数组for(int i = 0;i < 3; i++){for(int j = 0;j < 3; j++){printf("%-6d",(*p)[i][j]);}}printf("\n");    return 0;
}

案例2

/*
**指向一维数组的指针
*/#include <stdio.h>int t_pl()
{//创建一个一维数组int arr[] = {10,20,30,40,50};//计算数组大小int len = sizeof(arr) / sizeof(arr[0]);//创建一个数组指针指向一维数组arrint (*p)[len] = &arr;//借助数组指针遍历数组for(int i = 0; i < len; i++){//p 指向数组arr,p存储了数组arr的地址,如果要通过指针访问数组,就要对地址解引用(*p), *和[]在一起,[]的优先级大于*printf("%-4d", (*p)[i]);}printf("\n");
}/*
**指向二维数组的指针
*/int t_p2()
{//创建一个二维数组int arr[][3] = {{10,20,30},{100,2200,300},{1000,2000,3000}};//获取行和列的容量int row_len = sizeof(arr) / sizeof(arr[0]);int col_len = sizeof(arr[0]) / sizeof(arr[0][0]);//方式1(不推荐)  二维数组指针指向二维数组int (*p)[][3] = &arr;//遍历数组for(int i = 0;i < row_len; i++){for(int j = 0; j < col_len; j++){printf("%-6d", (*p)[i][j]);   } }printf("\n");//方式2(推荐)  一维数组指针指向二维数组,本质上是一维数组指针指向二维数组的行(默认首行)//&arr:获取该二维数组的地址,范围作用于整个数组//arr:数组名,默认指向第一个元素,这个就是行,默认首行,范围作用于整个行,等价于&arr[0]//数组参与指针运算,会降级为指针int (*p1)[3] = &arr[0];for(int i = 0; i < row_len;i++){for(int j = 0; j < col_len; j++){printf("%-6d", p1[i][j]);printf("%-6d", (*(p1+i))[j]);printf("%-6d", *(p1[i]+j));//列偏移printf("%-6d", *(*(p1+i)+j));}}printf("\n");    
}int main()
{return 0;
}

数组指针和指针数组

数组指针

指针和数组中符号优先级
() > [] > *
通过指针引用二维数组
int arr[][] = {{2000},{},{}};
表示形式含义地址/值
arr二维数组名,指向一维数组的arr[0],0行首地址2000
arr[0],*****(arr + 0),*arr0行0列元素地址,数组降级指针2000
arr + 1,&arr[1]1行首地址2008
arr[1],*(arr + 1)1行0列元素a[1] [0]的地址2008
arr[1]+2,*(arr + 1)+2,&arr[1] [2]1行2列元素a[1] [2]的地址2012
* (a[1]+2), * (* (arr+1)+2),arr[1] [2]1行2列元素a[1] [2]的值元素值为13

注意:二维数组中,数组整体的地址值 == 数组中0行元素的地址值 == 数组中0行0列元素的地址值

在这里插入图片描述

案例1
  • 用指向元素的指针变量输出二维数组元素的值

    #include <stdio.h>int mian()
    {//定义一个二维数组int arr[3][4] = {10,20,30,40,100,200,300,400,1000,2000,3000,4000};//定义一个指针变量,用来指向数组中的元素int *p = arr[0];//获取元素个数  行容量 * 列容量int len = (sizeof(arr) /sizeof(arr[0])) * (sizeof(arr[0]) / sizeof(arr[0][0]));//使用单层for循环遍历二维数组,列偏移for(; p < arr[0] + len; p++){//每四个一行  if((p - arr[0]) % 4 == 0 && p != arr[0])printf("\n"); printf("%-6d", *p); }printf("\n");return 0;
    }
    
案例2
  • 数组指针输出二维数组任意行任意列的元素的值

    在这里插入图片描述

指针数组

  • 定义:指针数组是一个数组,数组中每一个元素都是一个指针。

  • 特点:

    • 先有指针,后有数组
    • 指针数组的本质是一个数组,只是数组中的每一个元素是指针
  • 语法:

    数据类型 *数组名[容量];
    
案例
#include <stdio.h>int main()
{//定义三个变量int a = 10, b = 20, c = 30;//定义指针数组:先有指针,后有数组、int *arr[3] = {&a, &b, &c};//获取大小int len = sizeof(arr) / sizeof(arr[0]);//遍历数组for(int i = 0; i < len; i++){printf("%-3d", *arr[i]);  }printf("\n");return 0;
}
  • 建议:我们一般使用指针数组处理字符串,后续专门讲解
数组指针与指针数组的区别
对比项指针数组数组指针
定义数组元素均为指针的数组指向一个完整数组的指针
存储内容存储多个指针,每个元素指向不同的内存地址存储单个指针,指向一个完整的数组(首地址)
内存分配每个指针元素独立分配内存,可能分散指向的数组内存连续的,指针本身存储数组首地址
语法实例int *arr[5] 元素为5个int *指针int (*arr) [5] 指向5个int的数组的指针
访问方式通过下标访问指针元素,再解引用 *arr[i]先解引用指针得到数组,再访问元素 (*arr) [i]
使用场景管理多个独立指针(如字符串数组、动态结构体数组)操作多维数组(如传递二维数组的行指针)
内存布局[ptr1] --> 数据1 [ptr2] --> 数据2 …ptr --> [数据1] [数据2]…
示例代码int a = 1,b = 2;int *arr[] = {&a,&b};int arr[2] [3] = {1,2,3,4,5,6};int (*ptr)[3] = arr;
http://www.dtcms.com/a/314551.html

相关文章:

  • 【web应用】Maven:Java 生态的构建与依赖管理利器
  • LeetCode算法日记 - Day 1: 移动零、复写零
  • 排序算法——归并排序(图文演示)
  • 最小二乘法MSE
  • 【Linux】重生之从零开始学习运维之GTID复制
  • 【动态规划 | 回文字串问题】动态规划解回文问题的核心套路
  • docker镜像源配置教程,以及解决安装好docker配置镜像源后,出现报错。Job for docker.service failed
  • 在 C++ 中实现类似 Vue 3 的 Pinia 状态管理库
  • C++模板知识点3『std::initializer_list初始化时逗号表达式的执行顺序』
  • 2025-08月特辑---私有化部署gitea仓库
  • Android UI 组件系列(九):ListView 性能优化与 ViewHolder 模式实战
  • 信息安全概述
  • LightRAG:大模型时代的低成本检索利器
  • HCIP笔记1
  • OpenCV计算机视觉实战(18)——视频处理详解
  • 经典设计模式
  • 电商系统想撑住大流量?ZKmall开源商城靠微服务 + Spring Boot3 解决单体架构难题
  • VS2019 Qt5.14.2 OpenCV4.4.0 全流程安装及开发环境搭建与配置(工业相机环境配置)
  • SpringMVC在前后端分离架构中的执行流程详解
  • 【C++指南】STL stack 完全解读(一):从入门到掌握基础操作
  • 【C#】操作Execl和Word文件-2
  • 深入理解基础 IO:从 C 库函数到系统调用的全景指南
  • MCP安全机制深度剖析:权限控制与数据保护最佳实践
  • 液体泄漏识别误报率↓75%:陌讯多模态融合算法实战解析
  • vllm启动Qwen/Qwen3-Coder-30B-A3B-Instruct并支持工具调用
  • vue3 elementPlus el-dialog添加拖拽
  • Python实现Word转PDF全攻略:从入门到实战
  • 【人工智能99问】什么是Post-Training,包含哪些内容?(19/99)
  • 机器学习(12):拉索回归Lasso
  • 墨者学院SQL过滤字符后手工绕过漏洞测试(万能口令)