由int (*p)[5]与int *p[5]引发的学习与思考

  • 最近在大一上复习指针这部分时,有个C指针的特例一直困扰着我。我查阅了许多课本,也看了CSDN上许多大佬的理解。自我感觉受益匪浅,现记录下自己现阶段对这一类问题的学习和思考,以防遗忘。

  • 大佬Joerrot的博客:对行列指针关系的理论阐述
    大佬JZJZ73的博客:举遍历二维数组的例子体现行列指针的不同

  • 【1】int (*p)[5]

  • 本质: 首先分析一下,因为()的优先级大于[ ],所以这个表达式其实是在定义一个指针,本质是*p,而[5]在(*p)后面作用是修饰这个指针,补充说明这个指针指向的是一个包含5个元素的数组。

  • 在二维数组中的含义: 如果把这个指针指向的那个一维数组想像成二维数组的一行,那么这个指针其实就是所谓的行指针。

    # 行指针的定义:指向某一行,不指向具体的元素。

  • 例如一个二维数组a[5][4],那么p其实就是a,即第一行的地址(也可以说p就是&a[0],后面我会给大家讲到),同理p+1就是a+1……行指针在二维数组中是很常用的,特别是在对二维数组进行行操作时候能显示出它的便捷。说到行指针不可避免的要说到列指针,其实在二维数组中行指针指向的对象就是列指针。

    # 列指针的定义:指向行中具体的元素。

  • 由列指针的定义可以看出列指针其实很简单,就是一个指向数组中单个元素的指针,具体有关行指针和列指针关系问题,在上面大佬的两篇博客中也介绍了它们的关系:从列指针的角度看,只要在同一行,不管它们指向行中的哪个元素,它们的行地址都是在同一行的地址,所以它们的行地址都是一样的。同样我们得出结论:&列指针->行指针。 相反地可以推出:*行指针->列指针。 我最开始的理解就是把行指针看成是指向列指针的指针,这么想我当初认为一点错都没有,比如定义一个二维数组a[4][5],那么a就是行指针,*a是列指针,而常规的理解就是 *a是a所指向对象的内容。同理对于a[0]这一列指针来说,&a[0]就是行指针。具体表现形式如下:

  • 这么想是不是一点问题都没有?
    但如果行指针是指向指针的指针(二级指针)的话,那么行指针a与它所指向的指针(列指针) * a应该是不一样的,因为指针指向那块内存的地址肯定不等于指针指向的那块内存表示的内容。但事实上在二维数组中a与* a确实是相等的,下面是我在VS中test的截图:


    可以看出a与*a所表示的内容是一样的,那么说明二维数组其实并不是一个二级指针。其实想想也不对嘛,行指针+1后指针跨过的是一个一维数组的长度,比如int (*p)[5],那么p每次+1跨过的都是一个存有5个int型元素的一维数组。如果int a[5],那么跨过的就是sizeof(a)。但是二级指针因为是指向指针的指针,如果+1,仅仅跨过一个指针的大小(一般电脑中一个指针的大小默认是4个字节)。 所以只能说行指针等同于一个二级指针,但不是真正的二维指针。

  • 那么到底行指针与列指针关系图是怎样的呢?我们知道二维数组在栈中的存放形式与一维数组一样都是一个接一个存放的,并没有像矩阵这样存放。但是为了方便理解我们一般都会把它想象成一个矩阵的形式。以下这张图是我在谭浩强的《C程序设计(第五版)》中拍下来的,有这本书的读者也看以看一下书P244-245页对于这方面内容的介绍。

  • 注意 这下我们来解决上述问题a与* a相同的问题。首先我们知道了行指针int (* p)[5]与二级指针有着本质差别,所以不能按照常规二级指针的方式来理解它。(行指针是C语言里面的两大奇葩之一)那么我们应该怎样理解呢?对于二维数组a[m][n],a是二维数组的数组名,就是二维数组的首地址,即a[0][0]。(a也是行指针,表示的是二维数组第一行的首地址,也就是&a[0][0]) 而* a是列指针,指向元素a[0][0],那么* a自身的内容就是&a[0][0]。所以这两个是相等的。其实它们只是纯内存相同,但基类型是不同的。

  • 值得一提的是我发现a[0]有两种理解方式,一种可以理解为a[0]+0,也可以理解成a+0。 这两种理解方式一个是按行指针来理解,另一个是按列指针来理解。大家有什么想法吗?欢迎各位读者评论指点。

  • 个人认为指针与二维数组的关系其实并不算太难,只要注意下行指针int (* p)[n]是一个奇葩的指针定义形式就行,指向的是一个包含n个int型变量的数组。它与二级指针有着本质的差别。所以a与* a不能按照常规来理解。

  • 【2】int *p[5]

  • 本质: 这个定义相比于行指针就容易理解多了,首先p先与[5]结合,可以很容易判断出这是在定义一个数组,而前面的int * 则表示这个数组存放的元素都是int * 类型的,即每个元素都是一个指针。例如char *friends[5]={“smith”,“jackey”,“rose”,“marli”,“hanmeimei”}就表示这是一个包含5个字符指针的字符数组,每个字符指针都指向一个字符串。个人认为这类定义其实就可以看成一个二维字符数组去解决,即char friends[ ][5]={“smith”,“jackey”,“rose”,“marli”,“hanmeimei”}。

  • 实战 大家可以试一下这道题,我觉得很有意义。
    题目: 对char * friends[5]={“smith”,“jackey”,“rose”,“marli”,“hanmeimei”};进行查找某一个好朋友如"rose",如果找到删除它,没找到提示没有找到。

  • 以下为本题代码,因为VS中认为上述赋值为常量赋值,必须得要定义成const char * 所以我简单在Dev-c++5.11上写了一下此题的代码:

#include <stdio.h>
#include <string.h>
int search(char *p[5],char *);
int main()
{char *friends[5] = { "smith","jackey","rose","marli","hanmeimei"};char a[20];scanf("%s", a);int order;if ((order = search(friends, a)) == -1)printf("没有找到");else{for (int i = order; i < 4; i++){friends[i]=friends[i + 1];}for (int i = 0; i < 4; i++){printf("%s\t", friends[i]);}}
}int search(char *p[5],char *a)
{for (int i = 0; i < 5; i++){if (!strcmp(p[i], a)){return i;}}return -1;
}
  • 本博客内容皆为本人学习思考过程,因本人水平有限,如有不足之处欢迎指正。
    本人联系方式(QQ):1666271035

C/C++ 由int (*p)[5]与int *p[5]引发的学习与思考相关推荐

  1. const int * 、int * const、int const* 、const int a(){ } 和int a()const { }的区别和联系

    前言:很多人都把const int * .int * const.int const* 的区别和联系搞混,我自己在学习C++的过程中,也经常性          弄不 清楚,今天特意总结一下,作为学习 ...

  2. (volatile int)(x)与*(volatile int *)(x)

    在stackoverflow上看到这个问题 http://stackoverflow.com/questions/22758232/why-is-access-once-so-complex 原答主已 ...

  3. java indexof int,int indexOf(String str, int fromIndex)

    int indexOf(String str, int fromIndex) 描述 (Description) java.lang.String.indexOf(String str, int fro ...

  4. int * * a[10] int * (*a)[10]和 int(*a[10])() 是什么意思

    int* (*a)[10]; a是一个指向包含10个int型指针元素的数组. 比如: #include <stdio.h>int main() {// 定义数组,包含10个int*int* ...

  5. 编写一个函数itob(int n,char s[], int b),将整数n转换为以b进制的数。保存到s中。...

    void Reverse(char *left, char* right) {while (left < right){char tmp = *left;*left = *right;*righ ...

  6. const int、const int *、int *cosnt、const int * const、const int 的区别

    2018-01-04 创建人:Ruo_Xiao 2018-10-17 修改人:Ruo_Xiao 邮箱:xclsoftware@163.com 修改内容:增加对 delete 指向常量的指针的可行性的说 ...

  7. int a = 0 与 int a(0) int a(b)

    偶然看书发现了int a(0);这种写法,当时感觉很奇怪,于是网上搜索一番,发现了其中原因 C++ 延续了C 的编程思想,所以说有两套编程体系,面向对象及面向过程 int a = 0: 这种写法,就是 ...

  8. C专家编程—分析signal函数的原型声明{void (*signal(int sig,void (*func)(int)))(int)}(2)

    在ANSI标准中,signal()的声明如下:      void (*signal(int sig,void (*func)(int)))(int) signal是一个函数,它返回一个函数指针,后者 ...

  9. 【详解】C语言:编写一个函数itob(int n,char s[], int b),将整数n转换为以b进制的数。保存到s中。...

    #include<stdio.h>void itob(int n,char s[], int b) {int i=1;for(;i<=32;i++) //共循环了32次,保证得到32 ...

最新文章

  1. “上海名媛群”事件,我来说几句
  2. GHOST WIN8 64位软件自选安装专业优化版 201307 V1.0
  3. 调用 GetProcAddress 失败,在 ISAPI 筛选器 C:\Windows\Microsoft.NET...
  4. Daily Scrum9 11.13
  5. Python坑:bool是int的子类、列表循环中的变量泄露、lambda在闭包中会保存局部变量、重用全局变量
  6. (二)docker安装并持久化postgresql数据库
  7. 容器源码解析之LinkedHashSet(六)
  8. JSF2.0与纯JS框架
  9. 如何处理Partner function occurs less than specified in customizing error message
  10. DAG的深度优先搜索标记
  11. 蓝桥杯2015初赛-奇妙的数字
  12. hadoop的开发工具_Hadoop开发工具简介
  13. Linux 组与用户
  14. 数据集:102 flower、Cratech256、ImageNet数据集下载
  15. Python语法糖系列
  16. java odbc timesten_TimesTen 使用ODBC连接数据库的程序问题
  17. 2014传智播客ios第4期基础班+就业班
  18. 发布本人整理的面试问题大全,为准备找工作的同行们尽一份力 希望大家多补充或回答
  19. 孙德棣38岁中秋辞世
  20. python技术学什么好呢_想自学一些实用的技术,学什么好?

热门文章

  1. 1v1对战答题小程序
  2. mysql日期以及字符串相关格式化转换
  3. C、C++、java的区别
  4. 北斗和GPS定位在室外非常好用,但当手机进入室内时,它们的定位功能就很不准,甚至无法定位。我们可以开启WLAN扫描定位WIFI模块固定编码或者开启手机的A-GPS辅助定位通过基站,A-GPS服务器定位
  5. Linux 网络之netlink 简介
  6. 网络与信息安全工程师职位要求
  7. MySQL用逗号进行拼接、以逗号进行分割
  8. Java编程思想学习笔记4 - 序列化技术
  9. 常见的噪声:高斯、泊松和椒盐噪声
  10. php把buffer转化为图片_长微博生成(将html转化为图片)原理浅析