目录

  • 0. 引言
  • 1. 数组指针
  • 2. 指针数组
  • 3. 小结

本文使用运行环境如下:
操作系统:Ubuntu Linux 18.04 64 bit
编译环境:gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)

0. 引言

数组指针指针数组且听之类似,实际完全不同。数组指针意在“指针”,强调的是指针,即“指向数组的指针”;指针数组意在“数组”,强调的是数组,即“成员都是指针的数组”。

本文尝试阐述二者的不同之处。

1. 数组指针

数组指针如何定义与使用?先看一个示例程序arr_p.c

#include <stdio.h>int main()
{/* 定义一个有10个int成员的数组 */int arr_i[10] = {0,1,2,3,4,5,6,7,8,9};/* 定义一个指向有10个int成员的数组指针,并初始化为arr_i数组的地址 */int (*arri_p)[10] = &arr_i;/* 定义一个2*2的二维数组,在内存中以一维排列,实际是数组的数组arr数组成员类型为int (*)[2],数组元素为arr[0]和arr[1]对arr的数组成员arr[0]和arr[1],其本身也是数组,成员为int*/int arr[2][2] = {{1,2},{3,4}};/* 定义一个指向有2个int成员的数组指针,并初始化为arr数组第0个成员的地址 */int (*arr_p)[2] = &arr[0];/* 等价于int (*arr_p)[2] = arr; */printf("数组arr_i的地址:            %#lx\n", (unsigned long int)&arr_i);printf("数组指针arri_p的值:         %#lx\n", (unsigned long int)arri_p);printf("数组指针arri_p+1的值:       %#lx\n", (unsigned long int)(arri_p+1));printf("==========================================\n");printf("数组arr的地址:              %#lx\n", (unsigned long int)&arr);printf("数组指针arr_p的值:          %#lx\n", (unsigned long int)arr_p);printf("数组指针arr_p+1的值:        %#lx\n", (unsigned long int)(arr_p+1));printf("arr第一个成员的地址&arr[1]: %#lx\n", (unsigned long int)&arr[1]);printf("数组指针arr_p+1处的数组值:  %d\n", *(int*)(arr_p+1));return 0;
}

执行结果:

$ gcc arr_p.c
$ ./a.out
数组arr_i的地址:            0x7ffc5289ace0
数组指针arri_p的值:         0x7ffc5289ace0
数组指针arri_p+1的值:       0x7ffc5289ad08
==========================================
数组arr的地址:              0x7ffc5289acd0
数组指针arr_p的值:          0x7ffc5289acd0
数组指针arr_p+1的值:        0x7ffc5289acd8
arr第一个成员的地址&arr[1]: 0x7ffc5289acd8
数组指针arr_p+1处的数组值:  3

arr_i是一个有10个int成员的数组,数组类型为int [10]arri_p是这个数组类型的指针并指向了arr_i数组。在代码第20行和21行的打印中,arri_p指向了arr_i数组,因此数组arr_i的地址指针arri_p的值必然相等;

22行对指针arri_p进行指针运算,指针指向的类型是int [10],这里是64位系统64位程序,对指针+1运算就转化成了(unsigned long int)arri_p+sizeof(arr_i)*1arr_i数组占用内存大小为40个字节,因此指针arri_p+1之后将偏移40个字节(数组的大小),刚好0x7ffc5289ad08 - 0x7ffc5289ace0 = 0x28 = 40

这里数组指针arri_p+1之后其指向了数组范围之外,这样一看指针运算似乎就没什么用了,还有内存越界的风险。

再看13行往下的代码,定义了一个类型为int (*)[2]的二维数组arr,同样用一个数组指针arr_p指向arr数组,28行对指针arr_p+1时,其结果也是和arr数组偏移一个成员之后的地址相同。这里可以看出指针运算的原理是通用的,对指针+1将偏移指针指向对象的类型大小。

那么指针arr_p+1后偏移了多少字节?0x7ffc5289acd8 - 0x7ffc5289acd0 = 0x8 = 8,即一个int [2]成员的大小,就是arr数组第1行{1,2}所占用的空间,似乎不够有说服力,30行对arr_p+1后的位置进行取值,结果表明arr_p+1后指向了二维数组arr第2行第1个元素值为3,即arr_p+1后在二维数组中“换了一行”,因此有的地方也将数组指针称为“行指针”。

2. 指针数组

顾名思义,指针数组是一个成员为“同一指针类型的数组”,这里也通过一个示例程序进行说明。p_arr.c

#include <stdio.h>int main()
{int i = 0;int arr[3] = {1,2,3};int a = 10;/* int *p[4]等价于int *(p[4]) */int *p[4] = {&arr[0], &arr[1], &arr[2], &a};for(i = 0; i < sizeof(p)/sizeof(*p); i++){printf("*p[%d] = %d\n", i, *p[i]);}return 0;
}

运行结果:

$ gcc p_arr.c
$ ./a.out
*p[0] = 1
*p[1] = 2
*p[2] = 3
*p[3] = 10

指针数组较之数组指针易于理解,p是一个有4个成员的数组,每个成员都是int *类型,由于每个成员都是int *,因此p[i]既表示p数组的第i个成员,又表示某个int对象的地址。要访问p数组中保存的对象的地址所指向的对象,就需要对p数组中的成员解引用(取相应地址保存的数据),12行中*p[i]是对p数组中的第i个成员解引用,这种方式能够正常访问合法的地址对象。

3. 小结

  1. 数组指针本质是指针,是指向数组的指针;
  2. 指针数组本质是数组,是保存指针的数组;

从对指针数组和数组指针的分析来看,虽然两者都和指针相关,但指针和数组不可同日而语,对二者的混淆很大可能是中文概念的混淆。

数组指针 和 指针数组 的区别相关推荐

  1. (转)数组指针和指针数组的区别

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

  2. char[]数组与char *指针的区别

    char[]数组与char *指针的区别 问题描述 虽然很久之前有看过关于char指针和char数组的区别,但是当时没有系统的整理,到现在频繁遇到,在string,char[], char *中迷失了 ...

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

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

  4. 数组指针和指针数组的区别(1)

    一.指针数组和数组指针的内存布局 初学者总是分不出指针数组与数组指针的区别.其实很好理解: 指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定.它是"储存指针的数 ...

  5. 一维数组和二维数组的区别_数组指针和指针数组的区别

    数组指针和指针数组的区别 - hongcha_717 - 博客园​www.cnblogs.com 数组指针(也称行指针) 定义 int (*p)[n]; ()优先级高,首先说明p是一个指针,指向一个整 ...

  6. C/C++数组名与指针区别

    C/C++数组名与指针区别 引言 指针是C/C++语言的特色,而数组名与指针有太多的相似,甚至很多时候,数组名可以作为指针使用.于是乎,很多程序设计者就被搞糊涂了.而许多的大学老师,他们在C语言的教学 ...

  7. 神奇的判断数组名和指针的区别

    神奇的判断数组名和指针的区别 代码 代码 傻傻的区分不清楚数组名和指针的区别,下面的代码可以证明指针和数组名其实不是一个东西: // An highlighted block #include< ...

  8. 从编译器角度分析C语言中数组名和指针的区别

    从编译器角度分析C语言中数组名和指针的区别 数组名和指针是两个往往很容易让人们混淆的概念,很多人以为数组名就是一个指针,也有很多人知道数组名不同于指针但是仅知道数组名的值不能像指针一样改变. 例如你可 ...

  9. c#中byte数组0x_数组指针和指针数组的区别

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

  10. 指针笔记(指针数组和指向数组的指针,数组中a和a的区别等)

    指针数组和指向数组的指针 int *p[4]和int (*p)[4]有何区别? 前者是一个指针数组,数组大小为4,每一个元素都是一个指向int的指针 后者是指向int[4]类型数组的指针 以上代码若运 ...

最新文章

  1. Java web 环境搭建-Linux
  2. 十四:桥接者模式(发送各类短信案例)
  3. oracle判断一个字符是否是数字
  4. FI_ITEMS_MASS_CHANGE 批量更新 凭证文本 (凭证被锁、一些项目没更改到的解决方法)
  5. gitlab 将管理员权限移交给ldap账户_CDPDC中Atlas集成FreeIPA的LDAP认证
  6. php测试插入,php – 使用Symfony测试数据库插入
  7. mysql 存储过程 用户变量值_mysql:用户变量、系统变量、局部变量(存储过程中的)...
  8. java excel添加公式_Java添加、读取Excel公式
  9. automake的使用1
  10. 12月 Web 服务器调查:nginx 增长最快,微软市场份额最高
  11. 为什么在Linux执行自己的程序要在前面加./
  12. 中断 http请求 正在加载 取消http请求
  13. proteus元件图片_最完整的Proteus元件库元件名称及中英对照表下载
  14. 进阶Java架构师必看的15本书
  15. 周立功专访:周立功和他的团队已经找到了属于自己的道路
  16. 【nvidia】1.命令行方式安装nvidia显卡驱动
  17. c fflush函数
  18. 2022全国大学生数学建模竞赛
  19. css 如何实现文本竖排、横排展示
  20. 西南科技大学计算机专业全国排名,西南科技大学为什么在全国大学排名很低?...

热门文章

  1. 省技术市场举办技术合同政策及实务操作培训会
  2. iOS动画效果、绘制图形
  3. 云存储——搜狐网络U盘
  4. 【数字图像处理】【Matlab】【作业六】几何变换(平移、缩放、旋转、镜像、转置等)
  5. HFSS 初学者入门(一)
  6. 小白带你走进Eplan
  7. 联想r9000p电脑外接显示屏黑屏问题解决
  8. 数据结构之---非递归中序遍历二叉树
  9. win10 UWP Markdown 含源代码
  10. Jenkins+Docker自动化部署项目