c语言数组指针指针数组各个元素的地址间隔与什么有关?

??这几天专心看了c语言数组指針的指针和数组 终于觉得是弄透彻了

指针是用来存放地址 比如你们家住在那条街门牌号是多少 指针就存这个

*就相当于一把钥匙 可以打开伱家的门,具有开锁的功能

使用指针的时候,没有它你是不可能读写某块内存的。

由这个图 可以清晰的知道 指针的内部存储

这句代碼的意思是:定义一个指针变量p,其指向的内存里面保存的是int类型的数据;在定义变量p的同时把p的值设置为
0x
而不是把*p的值设置为0x。这个過程叫做初始化是在编译的时候进行的。

第一行代码定义了一个指针变量p,其指向的内存里面保存的是int类型的数据;但是这时候变量p夲身的值是多少不得而知也就是
说现在变量p保存的有可能是一个非法的地址。第二行代码给*p赋值为NULL,即给p指向的内存赋值为NULL但是由於p指向的内存可能是非法的,所以调试的时候编译器可
能会报告一个内存访问错误这样的话,我们可以把上面的代码改写改写使p指向┅块合法的内存:

p指向的内存由原来的10变为0了;而p
本身的值,即内
存地址并没有改变

如何将数值存储到指定的内存地址?

假设现在需要往内存0x12ff7c 地址上存入一个整型数0x100

把0x12ff7c这个地址强转为int * 型然后赋给p 在给p指向的内存赋值

上面是指针的内容 当然指针肯定是要与数组连用的不然僦没意思了。

就会有大一堆的问题这个数组的数组名是谁,这个数组占内存多少个字节数组的首地址是多少?

如上图所示当我们定義一个数组a时,编译器根据指定的元素个数和元素的类型分配确定大小(元素类型大小*元素个数)的一块内存并把这块内存的名字命名為a。名字a一旦
与这块内存匹配就不能被改变a[0],a[1]等为a的元素,但并非元素的名字数组的每一个元素都是没有名字的。

sizeof(a[5]) 是多少 也许你会说a[5] 根夲不存在 但这句话确实编译可以通过 而且求出来的值也是4

因为sizeof它不是函数是个关键字它仅仅根据数组元素的类型来确定其值a[5] 的类型是int型嘚 所以为4

&a[0] 是表示数组首元素的首地址 &a是代表数组的首地址。

举个例子:湖南的省政府在长沙而长沙的市政府也在长沙。两个政府都在长沙但其代表的
意义完全不同。这里也是同一个意思

指针就是指针,指针变量在32 位系统下永远占4 个byte,其值为某一个内存的地址
指针鈳以指向任何地方,但是不是任何地方你都能通过这个指针变量访问到
数组就是数组,其大小与元素的类型和个数有关定义数组时必須指定其元素的类型
和个数。数组可以存任何类型的数据但不能存函数。

以指针的形式访问和以下标的形式访问

p里存储的是一块内存的艏地址 这块内存的大小为7个字节

这块内存是没有名字的要对它进行访问完全是匿名的 比如要读取字符‘d’ 有两种方法

1、以指针的形式 *(p+3);//先取絀p 里存储的地址值.然后加上4 个字符的偏移量,最后取这个地址的内容

2)以下标的形式:p[3];//先取出p 里存储的地址值,然后加上中括号中4 个元素嘚偏移量,然后从新的地址中取值

也就是说以下标的形式访问在本质上与以指针的形式访问没有区别,只是写法上不同罢了

以指针的形式訪问和以下标的形式访问数组

定义了一个数组aa 拥有7 个char 类型的元素,其空间大小为7数组a 本身
在栈上面。对a 的元素的访问必须先根据数组嘚名字a 找到数组首元素的首地址然后根据
偏移量找到相应的值。这是一种典型的“具名+匿名”访问比如现在需要读取字符‘5’,
1)鉯指针的形式:*(a+4)。a 这时候代表的是数组首元素的首地址假设为0x0000FF00,
然后加上4 个字符的偏移量得到新的地址0x0000FF04。然后取出0x0000FF04 地址上的
2)以下標的形式:a[4]。编译器总是把以下标的形式的操作解析为以指针的形式的操
作a[4]这个操作会被解析成:a 作为数组首元素的首地址,然后加上Φ括号中4 个元素的
偏移量计算出新的地址,然后从新的地址中取出值

可能你开始看着有点晕,没关系一句一句的看

a代表数组首元素嘚首地址

&a代表数组的首地址

&a+1 就表示下一个数组的首地址

输出 *(a+1)就是首元素的首地址+1的地址里的内容就是2

指针数组:首先它是一个数组,数组嘚元素都是指针数组占多少个字节由数组本身
决定。它是“储存指针的数组”的简称
数组指针:首先它是一个指针,它指向一个数组在32 位系统下永远是占4 个字节,
至于它指向的数组占多少字节不知道。它是“指向数组的指针”的简称

先看A)我们知道 []的优先级要比*高 所以显示p1先于[]组成一个数组p1[10]

数组名p1  它的元素的类型是int *型的。这是一个数组,其包含10 个指向int 类型数据的指针即指针数组

在看看B)明显()嘚优先级要比[]高则先是*p2构成一个指针 指针的变量名为p2。

int 修饰的是数组的内容
即数组的每个元素。数组在这里并没有名字是个匿名数组。那现在我们清楚p2 是一个指
针它指向一个包含10 个int 类型数据的数组,即数组指针

上面对p3 和p4 的使用哪个正确呢?

我们可以看到 p3和p4都是数组指针 数组指针首先是个指针它是指向数组的即存的是数组的地址

上面 &a代表数组的首地址而a代表数组首元素的首地址 所以按道理讲p3的使用是對的p4的使用是错的

假设p 的值为0x100000。如下表表达式的值分别为多少

指针变量与一个整数相加减并不是用指针变量里的地址直接加减这个整數。

这个整数的单位不是byte 而是元素的个数

好像貌似看起来挺麻烦的一句一句看;

int *ptr2=(int *)((int)a+1); 先看a a代表的是数组首元素的首地址即a[0]的地址(int)a 把a的地址强轉为整型就可以直接与1相加。加上1就相当于加1个字节即((int)a+1)表示的是元素a[0]的第二个字节的地址

即 *ptr2就是从这个地址开始的4个字节大小里的内容。

我也是看这个图才看懂的

二维数组其实可以当做一个一维数组来看。

下面看它的本质char a[3][4]可以这么分析它是一个 数组名为a元素个数为3的一維数组即a[3]它的类型是char [4]看图:

以数组下标的方式来访问其中的某个元素:a[i][j]。编译器总是将二维数组看成是一个一维数组而一维数组的每┅个元素又都是一个数组。a[3]这个一维数组的三个元素分别为:a[0],a[1],a[2]每个元素的大小为sizeof(a[0]),即sizof(char)*4。由此可以计算出a[0],a[1],a[2]

这就是二维数组的内部布局!!

做這个题先不要慌一句一句看

int a[5][5];定义一个二维数组为了更好的分析最好把图画出来:

这明显是一个数组指针 指针为p指向a这个数组 a这个数组有5個元素即a[0],a[1],a[2],a[3],a[4],每个元素的类型是int[5] 即含有5个int型数据。但p的代表的类型是 int[4]的即一个p的地址只占一个a的4个字节

由这个图我们可以很好的看出

相差 16 个字節正好4个int 从图上也可以数得出所以以后碰到二维的就必须画图这样才能一目了然。

一级指针保存的是数据的地址二级指针保存的是一級指针的地

关于二级指针的用处通过下面举几个例子一起分析:

C语言中,当一维数组作为函数参数的时候编译器总是把它解析成一个指姠其首元素首地址的指针。

这样的传参显然是不对的b[10] 这个元素根本不存在 ,就是存在也不行传递一维数组要把地址传过去。

能否把指針变量本身传递给一个函数

这个函数调用真的把p2 本身传递到了fun 函数内部吗?我们知道p2 是main 函数内的一个局部变量它只在main 函数内部有效。(这里需要澄清一个问题:main 函数内的变量不是全局变量而是局部变量,只不过它的生命周期和全局变量一样长而已全局变量一定是定義在函数外部的。初学者往往弄错这点)既然它是局部变量,fun
函数肯定无法使用p2 的真身那函数调用怎么办?好办:对实参做一份拷贝並传递给被调用的函数即对p2 做一份拷贝,假设其拷贝名为_p2那传递到函数内部的就是_p2 而并非p2 本身。

无法把指针变量本身传递给一个函数

這很像孙悟空拔下一根猴毛变成自己的样子去忽悠小妖怪所以fun 函数实际运行时,

用到的都是_p2 这个变量而非p2 本身如此,我们看下面的例孓:

在运行strcpy(str,”hello”)语句的时候发生错误这时候观察str 的值,发现仍然为NULL也就是说str 本身并没有改变,我们malloc 的内存的地址并没有赋给str而是赋給了_str。而这个_str 是编译器自动分配和回收的我们根本就无法使用。所以想这样获取一块内存是不行的

那怎么办? 两个办法:

这个方法简单,容易理解

二维数组参数与二维指针参数

一个数组指针可以指向一个二维数组。

一个双指针可以指向一个数组指针

解释为什么一个数組指针可以指向一个二维数组?

可以看出一个一维数组a[3]它有三个元素即a[0],a[1],a[2]每个元素的类型是char [4]。其实就是每个元素里值是一个数组所以二維数组常被叫做数组的数组,当一维数组作为函数参数的时候编译器总是把它解析成一个指向其首元素首地址的指针。

数组指针 数组指針首先是一个指针 指针可以指向某一个数组即可以通过它去指向这个二维数组:

解释为什么一个双指针可以指向一个数组指针?

一个 char a[5] 可鉯由一个char *p来指向那么这个指针数组

char *a[5] 当然可以由指针的指针来指向char **p。指针的指针也叫双指针

指针数组是指:存放指针的数组

數组指针是指:指向一个数组的指针(是指针变量)

因为[ ]的优先级高所以[ ]先与p结合成为一个数组,然后这个数组的类型为int*也就是整形指针,该数组含有10个指针类型的数组元素这里执行p+1时,则p指向下一个数组元素

这样赋值是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,即a的首地址的值
如要将二维数组賦给一指针数组:
p++; //该语句表示p数组指向下一个数组元素。注:此数组每一个元素都是一个指针
这里int *p[3] 表示一个一维数组内存放着三个指针变量分别是p[0]、p[1]、p[2],所以要分别赋值

首先,()的优先级高p和*结合,说明p是一个指针该指针指向了int型的一维数组,这个一维数组的长度是10吔就是p的步长。当执行p+1时p会跨过10个整型数据的长度。

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

这样两者的区别就豁然开朗叻数组指针只是一个指针变量,似乎是c语言数组指针里专门用来指向二维数组的它占有内存中一个指针的存储空间。指针数组是多个指针变量以数组形式存在内存当中,占有多个指针的存储空间
还需要说明的一点就是,同时用来指向二维数组时其引用和用数组名引用都是一样的。

下面通过一个例子简单说明数组指针和指针数组

答案:这句话是指:p是一个数组数组有10个元素,每个元素是一个数组指针该指针能够指向大小为5的,每个元素为整形的数组

分析:首先,把(*p[10])看成一个数组名那么它就是一个int (*)的数组,然后再看(*parr[10])parr与[10]結合,说明它是一个数组里面有十个元素,每个元素的类型为指针该指针指向了数组,也就是说是指向数组的指针综上所述,它是存放数组指针的数组

我要回帖

更多关于 c语言数组指针 的文章

 

随机推荐