A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 曦正 中级黑马   /  2016-2-19 10:51  /  3903 人查看  /  18 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

C语言数组和指针对于初学者来言,指针是一个很大的坑,但是C语言能够那么多年来屹立不倒,也有赖于指针,没有指针C语言将什么也不是,下面简单分析一下C指针与数组的关系,笔记是自己整理的,如果有大牛发现有些不详尽或者有错误的话,欢迎补充指正,谢谢!也希望初学者能够学好指针,因为把指针搞懂了,后面那些什么Java、C++、OC等一些库函数的底层实现就比较好懂了。

C语言中,数组和指针密不可分,在系统内部实现上有着近乎一致的特性,只有在极少数情况下才需要人为区分;在C语言中只有一维数组的概念,多维数组在系统内部也是开辟一块平坦连续的空间,如果只看内存地址空间,是看不出多维数组的行列数的,比如array1,二维数组就是一个一维数组,数组内部元素是另一个数组,多维数组也是类似递归定义的。
数组有两个确定的参数:数组大小和下标为“0”的元素的地址。数组的下标操作实际上都是通过指针来进行的,数组和指针有一一对应的关系。

  • typedef int (*array_type)[3];
  • int array1[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
  • int array2[4][3]={1,2,3,4,5,6,7,8,9,10,11,12};
  • int array3[7]={1,2,3,4,5,6,7};
  • int *p1=array3;
  • int *q1=p1+1;
  • array_type p2=array2;
  • array_type q2=p2+2;

当输出array1[1][5]时,输出了“10”,在正常情况下,array1是没有[1][5]这个偏移的,但系统确实能正确的读取到相关的数值,就说明二维数值其实也就是一维数组;
array1[1][5]表示第2行的第6个数据,一行有4个数据,则4+6,切换到数组上就是array1[2][1],表示第3行的第2个数据,可以验证:数组内部数据是扁平化连续分布的,而且是内部转换成指针操作。
分析以上代码:
先建立一个新的用户类型:指针类型,该指针指向了一个拥有3个整型元素的数组;
如何理解数组名其实就是指向第一个数组元素的地址?
又如何解释数组元素?
一维数组array3中,p1的地址信息是array3的第1个变量的地址0x00318064,q1中的地址信息是array3中的第2个变量的地址0x000318068;虽然“q1=p1+1”,但是q1中地址信息并不是0x000318065,而是增加了1个int变量空间,指向了第2个元素。同理,二维数组array2中,p2中地址信息是array2第1个变量的地址0x000318064,q2中的地址是array2中第3个变量地址0x00031804c,这次增加的就不是2个int变量的空间那么简单了,而是23个int变量空间,这里的“3”指的是一维数组“int (array_type)[3]”,这次的步进单位不再是一个int空间,而是3个int变量的数组空间;

因为“int (*array_type)[3]”表示了一个拥有3个整型元素的数组,而array_type q2表示的是这一类“拥有3个整型元素的数组”的第0个元素,所以跨越了3个int变量的数组空间。

array3(一维数组名称)可以直接赋值给int指针,则它指的数组元素是int变量;
array2(二维数组名称)不能直接赋值给int
指针,只能直接赋值给一维数组指针(数组长度只能是3)的变量
那么,数组元素就可以这样解释:一维数组中直接就是定义数据类型;多维数组中是指除去最外围数组长度的剩余数组,即array[4][5]的数组元素:array[5],array[3][5][4]数组元素:array[5][4]。
可以认为,多维数组中的各维度在计算时是有优先级顺序。例如,array[3][4]意思是这个数组有3个元素,每个元素含有4个原子数据的数组;各维度在计算时,必须有固定的参考顺序,否则系统就会混乱。
如果指针指向数组中某一元素,则该指针的加减运算是以它指向的数组元素为单位的。即:如果数组元素是int类型,则指针+1会指向下一个int值;如果数组元素是以array[4]为类型,则指针+1会指向下一个array[4]的首地址。

一维数组和指针之间的微妙关系

分析:
无论几维数组,它的名称都表示指向该数组“初始元素”(基本类型、结构体、多为数组)的指针唯一的例外就是数组名称作为sizeof的操作时,结果时整个数组空间的大小,与起始元素无关;
array3表示第一个元素(int)的指针,那么array3就表示下标为“0”的元素引用,同理(array3+i)表示下标为i的元素引用,简写为array3,因为*(array3+i)等价于array3
在函数调用中,传递一维数组的名称时传递数组元素集合的首地址,有了首地址,函数就可以操纵任意长度的一维数组了,但是这个函数不知道该数组长度,而且编译器也不对数组下标进行有效性检查,这样可能会造成数据溢出,必要时需要用一个单独的参数传递数组长度。

  • #include <stdio.h>
  • int main(){
  •     int a[7]={1,2,3,4,5,6,7};//定义一个7个元素的数组
  •     int b=5;//定义一个变量b=5
  •     printf("%d",*(&b));//打印b地址中的内容
  •     printf("%d",*(a+6));//打印数组a第6个元素中的内容..注意从第0个开始数
  •     return 0;
  • }

也就是说,数组名其实就是数组第0个元素的地址,a就是获取数组a第0个元素地址里面的内容;而变量,则跟数组没有直接关系,需要去(&变量地址)才能取出变量地址里面的内容


评分

参与人数 2黑马币 +6 收起 理由
刘坤老师 + 4 赞一个!
梦想家z + 2 赞一个!

查看全部评分

18 个回复

倒序浏览
感谢分享.
回复 使用道具 举报
指针和数组 这是一个比较难的点
回复 使用道具 举报

可以交流一下
回复 使用道具 举报
chuanzhang 发表于 2016-2-19 20:29
指针和数组 这是一个比较难的点

是的,有什么问题也可以交流一下
回复 使用道具 举报
给力
回复 使用道具 举报
曦正 中级黑马 2016-2-20 08:47:31
7#
回复 使用道具 举报
可以可以
回复 使用道具 举报
chensc 金牌黑马 2016-2-21 07:51:04
9#
学习学习!
回复 使用道具 举报
感谢分享呢
回复 使用道具 举报

不用客气
回复 使用道具 举报
XJJ 初级黑马 2016-2-21 14:45:55
12#
写的很认真哦!!
回复 使用道具 举报
学习学习!
回复 使用道具 举报
谢谢分享
回复 使用道具 举报

金牌黑马
向金牌黑马学习才对
回复 使用道具 举报
顶贴顶贴顶贴
回复 使用道具 举报
点赞~!            
回复 使用道具 举报
学习学习
回复 使用道具 举报
谢谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马