关于指针数组与数组指针详解(知识点全面)

article/2025/9/22 4:03:29

1.目录

1.指针数组

2.数组指针

2.它们的区别


1.指针数组

如果一个数组中的所有元素保存的都是指针,那么我们就称它为指针数组。其一般形式为:

        数据类型    *数组名[常量表达式][常量表达式]...... ;

它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身的大小决定,每个元素都是一个指针。

 例如:char *arr[]={“Sunday”,“Monday”},存储了两个指针,第一个指针指向了字符串"Sunday",第二个指针指向了字符串"Monday",而sizeof(arr)=8,因为在32位平台,指针类型大小占4个字节。指针数组最重要的用途是对多个字符串进行处理操作,因为字符指针比二维数组更快更有效。

下面是个简单的例子

#include <stdio.h>
int main()
{//定义三个整型数组int a[5] = { 1,2,3,4,5 };int b[5] = { 6,4,8,3,1 };int c[5] = { 2,5,8,6,1 };//定义一个存放指向整型变量的指针的数组arrint* arr[] = { a,b,c };//通过接引用打印出三个一维数组的元素for (int i = 0; i < 3; i++){for (int j = 0; j < 5; j++){printf("%d ", *(arr[i]+j));}printf("\n");}return 0;
}

 结果如下:

      1 2 3 4 5

      6 4 8 3 1

      2 5 8 6 1

以上对arr解引用的方式有很多,它们都是等价的,我们来举个例子:

#include<stdio.h>
int main()
{int i = 0;int a[3][4] = { {1,2,3,4} ,{5,6,7,8} ,{9,10,11,12} };//定义一个二维数组int* pa[3];//定义一个指针数组for (i = 0; i < 3; i++)//给指针数组赋值pa[i] = a[i];printf("指针数组的内容为:\n");for (i = 0; i < 3; i++)//打印出指针数组的内容{int j;for (j = 0; j < 4; j++)printf("%d ", *(*(pa + i) + j));printf("\n");}//以下均为不同方式的解引用操作printf("不同解引用操作的结果为:\n");printf("%d,%d\n", a[1][1], *(pa[1] + 1));printf("%d,%d\n", a[1][1], *(*(pa+1) + 1));printf("%d,%d\n", a[1][1], (*(pa + 1))[1]);printf("%d,%d\n", a[1][1], pa[1][1]);return 0;
}

结果如下所示: 

指针数组的内容为:

1 2 3 4
5 6 7 8
9 10 11 12

不同解引用操作的结果为:

6,6
6,6
6,6
6,6

从以上例子可看出解引用有多种方式,它们的等价形式如下:

*( pa[i] + j )         //等价于 *( a[i] + j )

*( *(p+i) + j )        //等价于 *( *(a+j) + j )

( *(p+i) )[ j ]        //等价于( *(a+i) )[ j ]

p[ i ][ j ]                //等价于 a[i][j]

---------------------------------------------------------------------------------------------------------------------------------

补充(1)指针数组还可以和字符串数组相结合使用,请看下面的例子:

#include <stdio.h>
int main(){char *str[3] = {"lirendada","C语言","C Language"};printf("%s\n%s\n%s\n", str[0], str[1], str[2]);return 0;
}

结果如下:

lirendada

c语言

C Language

需要注意的是,字符数组 str 中存放的是字符串的首地址,不是字符串本身,字符串本身位于其他的内存区域,和字符数组是分开的。

也只有当指针数组中每个元素的类型都是char *时,才能像上面那样给指针数组赋值,其他类型不行。

 为了便于理解,可以将上面的字符串数组改成下面的形式,它们都是等价的。

#include <stdio.h>
int main(){char *str0 = "lirendada";char *str1 = "C语言";char *str2 = "C Language";char *str[3] = {str0, str1, str2};printf("%s\n%s\n%s\n", str[0], str[1], str[2]);return 0;
}

补充(2):二维数组与指针数组的区别

char *p1[]={"lirendada","C","C++"};
char p2[][8]={"liren","C","C++"};

*p1,*(p1+1),*(p1+2):所指向的字符串常量是不规则长度的,且sizeof(p1)=12。


p2[0],p2[1],p2[2]所指向的字符串都是一定长度的,且sizeof(p2)=24。


插播:大家阅读了头是不是有点大呢哈哈,点个赞或者三连支持一下作者,说不定脑瓜子突然就懂了呢!!!


 2.数组指针

注:因为数组指针对于一维数组的使用比较尴尬,对于一维数组,建议使用指针数组比较方便,这里只涉及到关于二维数组与数组指针的知识!!!

首先引入二维数组的定义:二维数组在概念上是二维的,有行有列,但在内存中所有的元素都是连续排列的,以下面的二维数组为例:

int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

从概念上理解,a的分布就像一个矩阵:

1        2        3        4

5        6        7        8

9       10      11      12

 从内存上理解,整个数组占用一块连续的内存:

 C语言中的二维数组是按行排列的,也就是先存放 a[0] 行,再存放 a[1] 行,最后存放 a[2] 行;每行中的 4 个元素也是依次存放。数组 a 为 int 类型,每个元素占用 4 个字节,整个数组共占用 4×(3×4) = 48 个字节。

C语言允许把一个二维数组分解成多个一维数组来处理。对于数组 a,它可以分解成三个一维数组,即 a[0]、a[1]、a[2]。每一个一维数组又包含了 4 个元素,例如 arr[0] 包含 a[0][0]、a[0][1]、a[0][2]、a[0][3]。

假设数组a中第0个元素的地址为1000,那么每个一维数组的首地址如下图所示:

 为了更好的理解指针和二维数组的关系,我们先来定义一个指向 a 的指针变量 p:

int (*p)[4] = a ; 

括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int [4],这正是 a 所包含的每个一维数组的类型。

[]的优先级高于*()是必须要加的,如果赤裸裸地写作int *p[4],那么应该理解为int *(p[4]),p 就成了一个指针数组,而不是二维数组指针。

对指针进行加法(减法)运算时,它前进(后退)的步长与它指向的数据类型有关,p 指向的数据类型是int [4],那么p+1就前进 4×4 = 16 个字节,p-1就后退 16 个字节,这正好是数组 a 所包含的每个一维数组的长度。也就是说,p+1会使得指针指向二维数组的下一行,p-1会使得指针指向数组的上一行。数组名 a 在表达式中也会被转换为和 p 等价的指针!

概念图如以下所示:

 下面我们就来探索一下如何使用指针 p 来访问二维数组中的每个元素。按照上面的定义:


1) p指向数组 a 的开头,也即第 0 行;p+1前进一行,指向第 1 行。


2) *(p+1)表示取地址上的数据,也就是整个第 1 行数据。注意是一行数据,是多个数据,不是第 1 行中的第 0 个元素,下面的运行结果有力地证明了这一点:

#include <stdio.h>
int main(){int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };int (*p)[4] = a;printf("%d\n", sizeof(*(p+1)));return 0;
}

运行结果为下面所示:

16

3) *(p+1)+1表示第 1 行第 1 个元素的地址。如何理解呢?

*(p+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,在定义时或者和 sizeof、& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针

4) *(*(p+1)+1)表示第 1 行第 1 个元素的值。很明显,增加一个 * 表示取地址上的数据

根据上面的结论,可以很容易推出以下的等价关系:

a+i == p+i
a[i] == p[i] == *(a+i) == *(p+i)
a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j)

 【实例】使用指针遍历二维数组。

#include <stdio.h>
int main(){int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};int(*p)[4];int i,j;p=a;for(i=0; i<3; i++){for(j=0; j<4; j++) printf("%2d  ",*(*(p+i)+j));printf("\n");}return 0;
}

运行结果:

 0   1   2   34   5   6   78   9  10   11

指针数组和二维数组指针的区别

指针数组和二维数组指针在定义时非常相似,只是括号的位置不同:

  1. int *(p1[5]); //指针数组,可以去掉括号直接写作 int *p1[5];
  2. int (*p2)[5];//二维数组指针,不能去掉括号

指针数组和二维数组指针有着本质上的区别:指针数组是一个数组,只是每个元素保存的都是指针,以上面的 p1 为例,在32位环境下它占用 4×5 = 20 个字节的内存。二维数组指针是一个指针,它指向一个二维数组,以上面的 p2 为例,它占用 4 个字节的内存。


http://chatgpt.dhexx.cn/article/gGA4iPMm.shtml

相关文章

指针数组(指针类型的数组)

顾名思义&#xff1a;指针类型的数组&#xff0c;首先是一个数组&#xff0c;数组元素存储的是指针。(中国的修饰词往往都在前面&#xff0c;而西方修饰词往往是放在后面) 语法如下&#xff1a; 目标类型 数组名称[元素个数] 如&#xff1a;int * p[3] 数组p有3个元素&#x…

数组指针和指针数组的区别

文章目录 前言 一、什么是指针数组&#xff1f; 1.定义 2.声明 3.指针数组的内存示意图 二、什么是数组指针&#xff1f; 1.定义 2.声明 3.内存示意图 三、如何区别指针数组和数组指针&#xff1f; 四、实践理解 总结 前言 这几天老师有问到指针数组和数组指针的区别&#xff…

C语言—指针数组与数组指针

前言&#xff1a; 看到标题的小伙伴可能会有点疑惑&#xff0c;什么是指针数组&#xff0c;数组指针&#xff1f;&#xff1f;傻傻分不清楚&#xff0c;不怕&#xff0c;听我慢慢道来。 正文&#xff1a; 要想弄清楚这两个概念&#xff0c;我们不妨举几个例子&#xff1a; …

指针数组和数组指针的区别及其详解

引言 对于指针数组和数组指针的概念&#xff0c;相信很多人经常会感到迷惑&#xff0c;见到二者一时不能分辨究竟对应哪一个才是对的。接下来我们来分析一下二者区别。 我们来看一下这个示例代码&#xff1a; int *ptr1[10]; int (*ptr2)[10];对于上述代码语句&#xff0c;你…

C语言学习—数组指针和指针数组的区别

前言 本文章对指针数组和数组指针的区别进行了分析介绍 一、数组指针和指针数组的定义 1.数组指针&#xff1a;定义 int (*p)[n]; 由于()的优先级高&#xff0c;首先说明p是一个int类型指针&#xff0c;它是指向一个整型(int)的一维数组&#xff0c;这个一维数组的长度是n&a…

指针数组和数组指针

1.什么是指针数组和数组指针 顾名思义&#xff1a;指针数组是“存放指针的数组”&#xff0c;这个变量是一个数组&#xff0c;用指针修饰&#xff0c;数组中的每个元素都是指针。 数组指针是“指向数组的指针”&#xff0c;这个变量是一个指针&#xff0c;用数组修饰&#xf…

指针数组和数组指针(非常易懂)

指针数组与数组指针 目录&#xff1a; 1.指针与一维数组 2.指针与二维数组 3.指针数组与数组指针 1.指针与一维数组 当定义一个一维数组时&#xff0c;系统会在内存中为改数组分配一个储存空间&#xff0c;其数组的变量名就是数组的首地址。若定义一个指针变量&#xff0c;并…

数组指针和指针数组

首先&#xff0c;理解一下数组指针和指针数组这两个名词&#xff1a; “数组指针”和“指针数组”&#xff0c;只要在名词中间加上“的”字&#xff0c;就知道中心了—— 数组的指针&#xff1a;是一个指针&#xff0c;什么样的指针呢&#xff1f;指向数组的指针。 指针的数…

如何下载风云卫星数据?

如何下载风云卫星数据&#xff1f; 这个是下载风云数据的网址&#xff1a; http://satellite.nsmc.org.cn/PortalSite/Data/Satellite.aspx 1.查找数据 步骤见如图1&#xff1a; 2.选择数据 选择“搜索”以后就就出现图2这个页面&#xff1a;文件名如果被省略了&#xff0…

总结部分SAR卫星及其参数以及SAR卫星发展的趋势

总结国内外失效、在轨和未来发射的SAR卫星及其参数 国内的SAR卫星及其参数 1、高分三号卫星 高分三号卫星(GF-3)于2016年8月10日成功发射&#xff0c;是我国首颗分辨率达到1米的C频段多极化合成孔径雷达(SAR)卫星&#xff0c;自然资源部为其主用户。 GF-3星的分辨率可以达到…

spot卫星介绍与数据下载

1.简介 1.1基本信息 SPOT系列卫星是法国空间研究中心&#xff08;CNES&#xff09;研制的一种地球观测卫星系统&#xff0c;已发射SPOT卫星1-7号。目前CNES已开放spot1-5的卫星数据&#xff0c;可免费下载数据的时间范围为1986年-2014年。 1.2卫星年表 名称信息SPOT-11986年…

空气污染气体卫星数据的下载教程

影响空气质量的主要气体有&#xff1a;二氧化硫、一氧化碳、二氧化氮、可吸入颗粒和臭氧等。我们可以通过Giovanni平台下载空气污染气体的卫星产品数据。 Giovanni平台介绍 Giovanni&#xff0c; 是NASA 旗下的地球科学可视化工具。通过简单的操作&#xff0c;即可将NASA 相关…

GRACE卫星介绍与解密数据下载

1 简介 1.1 基本信息 GRACE &#xff0c;Gravity Recovery and Climate Experiment&#xff0c;由 NASA 和德国宇航中心&#xff08;DLR&#xff09;联合研制&#xff0c;于 2002 年 3 月 17 日在发射。发射 时其预计寿命为 5 年&#xff0c;一直超期服役到2017年坠毁。后继卫…

风云气象卫星数据处理调研报告

风云卫星遥感数据服务平台 http://www.nsmc.org.cn/NSMC/Home/Index.html http://data.nsmc.org.cn/PortalSite/Default.aspx 风云四号气象卫星是我国第二代静止气象卫星&#xff0c;充分考虑海洋、农业、林业、水利以及环境、空间科学等领域的需求&#xff0c;以实现综合利用…

worldview卫星数据的查询方法

地理遥感生态网平台代理worldview1、worldview2、worldview3、worldview4、quickbird、geoeye、ikonos、 pleiades、spot1、spot2、spot3、spot4、spot5、spot6、spot7、landsat5(tm)、landsat(etm)、landsat8、rapideye、alos、aster、Hyperion(EO-1)、kompsat2、kompsat-3、k…

PL(Planet)卫星群遥感数据介绍及应用

1. 卫星介绍 星球实验室&#xff08;Planet Labs&#xff09;是由前美国空间局&#xff08;NASA&#xff09;科学家于2010年在旧金山成立的一家遥感卫星数据公司。该公司在世界上首次研发成功微卫星群技术&#xff0c;是世界上唯一具有全球高分辨率高频次全覆盖的遥感卫星系统…

CloudSat卫星数据下载

介绍 CloudSat标准数据产品由位于柯林斯堡的科罗拉多州立大学大气合作研究机构的CloudSat数据处理中心分发。数据产品ID以及产品名如下&#xff1a; 下载 方式1&#xff0c;交互式下载。 在官网注册&#xff0c;官网&#xff1a;http://www.cloudsat.cira.colostate.edu/o…

预处理——HJ卫星数据

&#xff08;遥感数据打开后&#xff0c;为了呈现更好的显示结果&#xff0c;都进行2%的拉伸&#xff0c;下面不再赘述&#xff09; &#xff08;一&#xff09;图像裁剪 1、打开2016年的HJ1A-CCD2卫星数据→File→Save as→Spatial Subset→选择要裁剪的东平湖区域→OK 2、…

基于学术研究风云卫星数据下载教程

目录 一、相关网址 1.登录注册网址&#xff1a;国家卫星气象中心 2.风云数据服务客户端下载网址 3.风云卫星遥感数据服务网址 二、下载数据步骤 1.首先在注册登录网址&#xff0c;注册一个账户 2.待账户审核后&#xff0c;登录账户即可搜索并下载数据 三、相关工具下载…

葵花(Himawari)8/9卫星数据处理

李国春 葵花8&#xff08;含葵花9&#xff0c;下同&#xff09;是静止气象卫星&#xff0c;数据范围是星下点为140E赤道上空的大圆盘。空间分辨率有500m、1km和2km三种。虽然其空间分辨率不高&#xff0c;但是有极高的时间分辨率&#xff0c;观测数据刷新仅10分钟。这对一些生…