0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【C语言进阶】“数组指针”和“指针数组”都是啥跟啥?

嵌入式物联网开发 来源:嵌入式物联网开发 作者:嵌入式物联网开发 2022-08-31 13:21 次阅读

相信学习过C语言的童鞋,一定被这2个东西折腾过吧?究竟它们都是何方神圣呢?带着这个问题,笔者想通过本文给你一个清晰的答案。通过阅读本文,你将了解到以下内容:

  • 什么是数组指针?
  • 什么是指针数组?
  • 数组指针和指针数组有什么区别?
  • 使用指针数组的注意事项

什么是数组指针?


​ 【数组指针】,从字面意思上理解,就是一个【指针】;“数组”只是起到了修饰“指针”的作用,所以连起来的意思就是【指向数组的指针】。这一点与上一篇文章介绍 【函数指针】有异曲同工的含义。

​ 从C语言的语法上理解,数组指针的表示形式为:

//定义一个一维数组
int a[3];

//定义一个指针,指向一维数组的首地址
int *q = a;

//定义一个3行4列的二维数组
int b[3][4]; 

//定义一个数组指针,它指向二维数组的首地址
int (*p)[4] = b;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eQIadh0d-1661923181862)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

​ 从数组指针的形式上看,因为()运算符拥有最高优先级,所以整个语句优先被解释成一个指针;接着,这个指针再指向另一个数组的首地址,[x]接上该数组的列数,即得到如上的数组指针的定义。

​ 经过这个例子,我们可以看到,数组指针一般用于表达多维数组,对比起多维数组的表示,采用数组指针的形式可以在一定程度上理解难度减小了。比如,有了如上的数组指针定义后,这里b是个二维数组的数组名,相当于一个二级指针常量;p是一个指针变量,它指向包含5个int元素的一维数组,此时p的增量以它所指向的**一维数组长度为单位;*(**p+i)是一维数组b[i][0]的地址;(p+2)+3表示b[2][3]地址(第一行为0行,第一列为0列),(*(p+2)+3)表示b[2][3]的值。


什么是指针数组?


​ 【指针数组】,从字面意思上理解,它就是一个数组,只不过“指针”是用于修饰“数组”的,所以合起来理解就是:【一个数组元素存放的是指针的数组】。

​ 从C语言的语法上理解,【指针数组】的定义形式如下所示:

//定义一个char *的指针数组
char *p[5];

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qud5CpbF-1661923181865)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

​ 这里,它表示的含义是,一个由5个元素组成的一维数组,每个数组元素都是一个指针(地址)。访问数组的元素,我们都是采用 数组名[数组下标] 的形式访问的,那么【指针数组】也不例外,访问第一个元素,则是p[0];同理,p[2]表示的是第3个指针。


数组指针和指针数组有什么区别?


​ 从字面上看,确实很容易混淆两者的概念;我们理解的时候,需要注意名词谁先谁后。一般来说,在前面的名词是用于修饰后面的名词,而后面的名词决定了整个词组的性质。

【数组指针】:数组修饰指针,它的本质是一个指针;一般这个指针指向一个二维数组,形式为: int (*p)[M]。

【指针数组】:指针修饰数组,它的本质是一个数组;这个数组里面的元素,存放的都是指针,形式为: int *p[M]。

​ 如上定义中,第一个M表示二维数组的列数,第二个M表示的指针数组(一维数组)的元素个数。

​ 数据访问方面:

  • (*p)[0] 表示的是二维数组中的第一行的首地址;
  • p[0] 表示的指针数组的第一个元素,即第一个指针地址。

使用指针数组的注意事项


​ 这两个概念不但容易混淆,而且在使用过程中也是十分容易出错,曾经笔者在【指针数组】上摘过跟头。现将出错的教训分享给大家:

  • 求一个指针数组的中元素的个数,不是简单地使用sizeof

​ 比如有一个指针数组的定义:

char *p[5];

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CRsvrkY7-1661923181868)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

​ 假设在编程平台上,一个指针所占用的地址空间是4个字节,即sizeof(char ) = 4;那么如果使用sizeof§去求这个指针数组所占用的地址空间时,求得的大小是45=20;而每个元素都是char *类型,所以求得指针元素的个数为: 20 / 4 = 5。

​ 于是,我们得出一个公式,求指针数组的元素个数:

//直接求得指针数组p的元素个数
cnt = sizeof(p) / sizeof(p[0]);

//很多时候,我们会定义一个宏来表示,形式如下:

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a)  (sizeof(a) / sizeof(a[0]))
#endif

//使用ARRAY_SIZE宏求指针数组p的元素个数
cnt = ARRAY_SIZE(p);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qwfXvoOo-1661923181869)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

  • 定义字符串类型的指针数组时,每个元素(字符串)注意用分号隔开,否则可能出现意想不到的事情

​ 假设有以下2个指针数组的定义:

const char *p1[] = 
{
    "12345",
    "23456",
    "34567",
    "45678",
    "56789",
};

const char *p2[] = 
{
    "12345",
    "23456"
    "34567",
    "45678"
    "56789",
};

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wt3RK9bs-1661923181874)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

​ 如果你不仔细看,你可能觉得p1和p2的定义是一致;仔细一看,原来p2中少了2个分号;而这2个分号一少,直接就导致p2的最终被编译器识别成的定义为:

//最终被识别的定义
const char *p2[] = 
{
    "12345",
    "2345634567",
    "4567856789",
};

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aNeQ6PqX-1661923181875)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

​ 看到区别了吗?由于分号的缺失导致前后相邻的字符串被结合在一块,被连接成一个更长的字符串,而这种【拼接】是编译器自动识别完成的,它不会提示任何错误,因为在它看来根本就不是错误。对使用者而言,这样定义一改变,原本本应该为5个元素的字符串数组,就变成了3个字符串的数组,这简直就是灾难啊!!!


​ 以上就是笔者对【数组指针】和【指针数组】的实践,得出的切实理解,希望能够帮助大家更近一步地理解它们。以上提及观点,均为笔者本人的观点,如有纰漏之处,还望指正。感激不尽。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136691
  • 数组指针
    +关注

    关注

    0

    文章

    5

    浏览量

    5232
  • 函数指针
    +关注

    关注

    2

    文章

    56

    浏览量

    3778
收藏 人收藏

    评论

    相关推荐

    C语言数组名和指针

    指针C/C++语言的特色,而数组名与指针有太多的相似,甚至很多时候,
    发表于 08-27 17:48 723次阅读

    C语言数组指针的区别

    大家好,我是嵌入式老林,从事嵌入式软件开发多年,今天分享的内容是C语言数组指针的区别,希望能对你有所帮助。
    发表于 07-11 12:40 375次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>数组</b>和<b class='flag-5'>指针</b>的区别

    C语言中指针数组数组指针的区别

    指针数组之间存在着紧密的关系。在本文中,我们将探讨指针数组的关系、指针算术和数组遍历、多维
    发表于 08-17 15:29 410次阅读

    转: 吊丝整理C语言 数组指针 指针数组

    主要针对指针数组数组指针。大家看看对不对。没有好办法把文档内容贴出来。先贴几个图片吧。里面有几个错误,等你自己发掘吧,这样你就可以笑笑说
    发表于 08-08 10:03

    C语言入门教程-用指针操作数组

    C语言入门教程 在C语言中,数组指针的关系十分密切。要想有效地使用
    发表于 07-29 12:18 1491次阅读

    指针数组都是C语言的精髓所在 两者有何联系区别

    指针数组都是C语言的精髓所在,对于很多C程序员来说,如果你问这样一个问题:
    的头像 发表于 05-27 14:51 4143次阅读
    <b class='flag-5'>指针</b>和<b class='flag-5'>数组</b><b class='flag-5'>都是</b><b class='flag-5'>C</b><b class='flag-5'>语言</b>的精髓所在 两者有何联系区别

    指针数组数组指针的区别

    这里我们区分两个重要的概念:指针数组数组指针
    的头像 发表于 06-29 15:30 2w次阅读
    <b class='flag-5'>指针</b><b class='flag-5'>数组</b>和<b class='flag-5'>数组</b><b class='flag-5'>指针</b>的区别

    理解函数指针、函数指针数组、函数指针数组指针

    理解函数指针、函数指针数组、函数指针数组指针
    的头像 发表于 06-29 15:38 1.5w次阅读
    理解函数<b class='flag-5'>指针</b>、函数<b class='flag-5'>指针</b><b class='flag-5'>数组</b>、函数<b class='flag-5'>指针</b><b class='flag-5'>数组</b>的<b class='flag-5'>指针</b>

    C语言中指针数组

    #define SIZE 10int arry[SIZE]={0,1,2,3,4,5,6,7,8,9}; //数组名arry表示数组首元素的地址*int p,temp;//可直接初始化定义指针
    发表于 01-13 13:11 3次下载
    <b class='flag-5'>C</b><b class='flag-5'>语言中指针</b>与<b class='flag-5'>数组</b>

    C语言指针数组的区别

    C语言教程中我们使用通过数组名通过偏移和指针偏移都可以遍历数组,那么指针
    的头像 发表于 07-18 16:29 1924次阅读

    二维数组数组指针以及指针数组

    二维数组数组指针以及指针数组
    的头像 发表于 08-16 09:02 2653次阅读

    C语言数组元素的指针

    C语言调用函数时虚实结合的方法都是采用“值传递”方式,当用变量名作为函数参数时传递的是变量的值,当用数组名作为函数参数时。 由于数组
    的头像 发表于 03-10 14:45 894次阅读

    C语言中什么是指针数组

    C语言中一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,
    的头像 发表于 03-10 15:26 1749次阅读

    数组指针不能混用的情况

    数组指针不能混用的情况  数组指针C/C++ 中非常常见的特性和概念。然而,在某些情况下
    的头像 发表于 12-07 13:46 599次阅读

    数组指针不相同吗?数组指针有哪些区别

    数组就是指针指针就是数组,这样的言论在评论区看到不下于10次。
    的头像 发表于 12-13 16:34 1487次阅读
    <b class='flag-5'>数组</b>和<b class='flag-5'>指针</b>不相同吗?<b class='flag-5'>数组</b>和<b class='flag-5'>指针</b>有哪些区别