数组指针(也称行指针)
定义 int (*p)[n];
()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。

如要将二维数组赋给一指针,应这样赋值:
int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
 p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
 p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

所以数组指针也称指向一维数组的指针,亦称行指针。

指针数组
定义 int *p[n];
[]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1时,则p指向下一个数组元素,这样赋值是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3][4];
p++; //该语句表示p数组指向下一个数组元素。注:此数组每一个元素都是一个指针
for(i=0;i<3;i++)
p[i]=a[i]
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]
所以要分别赋值。

这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。
还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。
比如要表示数组中i行j列一个元素:
*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]

优先级:()>[]>*

出处:http://www.cnblogs.com/hongcha717/archive/2010/10/24/1859780.html

=========================================================================

再论a 和&a 之间的区别

既然这样,那问题就来了。前面我们讲过a 和&a 之间的区别,现在再来看看下面的代码:
int main()
{
   char a[5]={'A','B','C','D'};
   char (*p3)[5] = &a;
   char (*p4)[5] = a;
   return 0;
}
上面对p3 和p4 的使用,哪个正确呢?p3+1 的值会是什么?p4+1 的值又会是什么?毫无疑问,p3 和p4 都是数组指针,指向的是整个数组。&a 是整个数组的首地址,a是数组首元素的首地址,其值相同但意义不同。在C 语言里,赋值符号“=”号两边的数据类型必须是相同的,如果不同需要显示或隐式的类型转换。p3 这个定义的“=”号两边的数据类型完全一致,而p4 这个定义的“=”号两边的数据类型就不一致了。左边的类型是指向整个数组的指针,右边的数据类型是指向单个字符的指针。在Visual C++6.0 上给出如下警告:
   warning C4047: 'initializing' : 'char (*)[5]' differs in levels of indirection from 'char *'。
还好,这里虽然给出了警告,但由于&a 和a 的值一样,而变量作为右值时编译器只是取变量的值,所以运行并没有什么问题。不过我仍然警告你别这么用。

.char (*p2)[5]=a;必须使用强制转换,如:char (*p2)[5]=(char (*)[5])a;

=========================================================================

地址的强制转换

先看下面这个例子:
struct Test
{
   int Num;
   char *pcName;
   short sDate;
   char cha[2];
   short sBa[4];
}*p;

假设p 的值为0x100000。如下表表达式的值分别为多少?
   p + 0x1 = 0x___ ?
   (unsigned long)p + 0x1 = 0x___?
   (unsigned int*)p + 0x1 = 0x___?
我相信会有很多人一开始没看明白这个问题是什么意思。其实我们再仔细看看,这个知识点似曾相识。一个指针变量与一个整数相加减,到底该怎么解析呢?

还记得前面我们的表达式“a+1”与“&a+1”之间的区别吗?其实这里也一样。指针变量与一个整数相加减并不是用指针变量里的地址直接加减这个整数。这个整数的单位不是byte 而是元素的个数。所以:p + 0x1 的值为0x100000+sizof(Test)*0x1。至于此结构体的大小为20byte,前面的章节已经详细讲解过。所以p +0x1 的值为:0x100014。

(unsigned long)p + 0x1 的值呢?这里涉及到强制转换,将指针变量p 保存的值强制转换成无符号的长整型数。任何数值一旦被强制转换,其类型就改变了。所以这个表达式其实就是一个无符号的长整型数加上另一个整数。所以其值为:0x100001。

(unsigned int*)p + 0x1 的值呢?这里的p 被强制转换成一个指向无符号整型的指针。所以其值为:0x100000+sizof(unsigned int)*0x1,等于0x100004。

上面这个问题似乎还没啥技术含量,下面就来个有技术含量的:在x86 系统下,其值为多少?
intmain()
{
   int a[4]={1,2,3,4};
   int *ptr1=(int *)(&a+1);//指向a数组后面的内存单元,&a+1表示向后移16个存储单元
   int *ptr2=(int *)((int)a+1);//表示a的存储单元的地址增加一个字节
   printf("%x,%x",ptr1[-1],*ptr2);//ptr1[-1]其实指向的是a数组的最后一个单元,*ptr1则表示a数组的地址后移一个字节之后的4个连续存储单元所存储的值
   return 0;
}
这是我讲课时一个学生问我的题,他在网上看到的,据说难倒了n 个人。我看题之后告诉他,这些人肯定不懂汇编,一个懂汇编的人,这种题实在是小case。下面就来分析分析这个问题:

根据上面的讲解,&a+1 与a+1 的区别已经清楚。

ptr1:将&a+1 的值强制转换成int*类型,赋值给int* 类型的变量ptr,ptr1 肯定指到数组a 的下一个int 类型数据了。ptr1[-1]被解析成*(ptr1-1),即ptr1 往后退4 个byte。所以其值为0x4。
ptr2:按照上面的讲解,(int)a+1 的值是元素a[0]的第二个字节的地址。然后把这个地址强制转换成int*类型的值赋给ptr2,也就是说*ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。

转载于:https://www.cnblogs.com/zhangxin253245514/p/6674805.html

c语言回顾之指针数组和数组指针相关推荐

  1. C语言 指针+二维数组详解 (应付期末、考研的最强笔记,建议收藏)

    哈喽!这里是一只派大鑫,不是派大星.本着基础不牢,地动山摇的学习态度,从基础的C语言语法讲到算法再到更高级的语法及框架的学习.更好地让同样热爱编程(或是应付期末考试 狗头.jpg)的大家能够在学习阶段 ...

  2. C语言 数组的指针和指向数组的指针变量

    一.回顾二维数组和多维数组的概念 int a[3][4];  //二维数组 int a[2][3]4];  //多维数组 二.指向多维数组的指针和指针变量的探究 可以把a看成是一个一维数组,这个一维数 ...

  3. 关于C语言中的数组指针、指针数组以及二级指针

    概念解释 数组指针:首先它是一个指针,它指向一个数组,即指向数组的指针:在32 位系统下永远是占4 个字节,至于它指向的数组占多少字节,不知道.数组指针指向的是数组中的一个具体元素,而不是整个数组,所 ...

  4. c语言中的字节和元素,C语言指向数组元素的指针

    指向数组元素的指针和运算法则 所谓指向数组元素的指针,其本质还是变量的指针.因为数组中的每个元素,其实都可以直接看成是一个变量,所以指向数组元素的指针,也就是变量的指针. 指向数组元素的指针不难,但很 ...

  5. C语言指针数组与数组指针的区别

    C语言指针数组与数组指针的区别 首先,顾名思义 数组指针是一个指针,是指向一个数组的指针,如 int (a*)[5]:这就是一个指向含有5个元素的数组的指针 指针数组是一个数组,它包含的元素全是指针变 ...

  6. 【C语言】12-指向一维数组元素的指针

    本文目录 一.用指针指向一维数组的元素 二.用指针遍历数组元素 三.指针与数组的总结 四.数组.指针与函数参数 说明:这个C语言专题,是学习iOS开发的前奏.也为了让有面向对象语言开发经验的程序员,能 ...

  7. C语言学习笔记--预编译/宏定义/数组/参数传递/函数指针

    目录 预编译 值传递.指针传递.引用传递 数组 typedef 函数指针 预编译 预编译又叫预处理.预编译不是编译,而是编译前的处理.这个操作是在正式编译之前由系统自动完成的.#define 和 #i ...

  8. 【C 语言】数组与指针操作 ( 数组符号 [] 与 指针 * 符号 的 联系 与 区别 | 数组符号 [] 与 指针 * 符号 使用效果 基本等价 | 数组首地址 与 指针 本质区别 )

    文章目录 前言 一.数组符号 [] 与 指针 * 符号 使用效果 基本等价 二.数组首地址 与 指针 本质区别 前言 参考 [C 语言]指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方 ...

  9. 【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  10. 【C 语言】结构体相关 的 函数 指针 数组

    . 作者 : 万境绝尘 转载请注明出处 : http://www.hanshuliang.com/?post=30 . 结构体概述 : 结构体是 多个 变量的集合, 变量的类型可以不同; -- 可进行 ...

最新文章

  1. Servlet中的配置 web.xml
  2. squid启动失败的解决办法
  3. Python进阶之路:namedtuple
  4. 过渡效果_12个酷炫创意的动画过渡效果AE模板
  5. CentOS 7.6 安装 Maven 3.6.3
  6. linux 账号密码 字段,详解Linux中的用户密码管理命令passwd和change
  7. 企业级项目实战讲解!javamap排序规则
  8. Spring MVC-视图解析器(View Resolverr)-内部资源视图解析器(Internal Resource View Resolver)示例(转载实践)...
  9. 30个Linux安装案例,Make和Makefile说明,Linux工具,容器安全性,DevOps技巧等
  10. chart控件删除最左边点_常见功能测试点的测试用例大全
  11. Activiti 学习笔记记录(2016-8-31)
  12. PrinterLogic 厂商修复影响所有联网端点的3个RCE漏洞
  13. poj1470 LCA倍增法
  14. android自定义表格布局
  15. 一步步学Qt,第九天-QSTL与STL-Qvector,vector
  16. ElasticJob汇总
  17. 安装pdfFactory Pro
  18. 如何清空各种浏览器缓存
  19. 三本 计算机专业,四川哪些三本大学的计算机专业最好?
  20. 真百式 - 饺子的做法

热门文章

  1. 在CAD中容易混淆的概念
  2. Linux日志终极指南
  3. java中的Map每次只能put一次,写段增强的put,可以一次put很多次
  4. memcached命令
  5. Mac下启动AndroidStudio失败
  6. python-unicode十进制数字转中文
  7. dexposed框架Android在线热修复
  8. Luogu1306 斐波那契公约数
  9. [UESTC SC T4] Chika 的烦恼
  10. 电商项目的app学习笔记(二)---创建登陆界面