鱼C论坛

 找回密码
 立即注册
查看: 1471|回复: 8

[已解决]数组指针元素个数怎么决定

[复制链接]
发表于 2019-7-21 10:22:24 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在定义一个数组指针时,元素个数是指行数还是列数
int array[2][3]={{0,1,2},{3,4,5}};
int(*p)[3]=array;
这里数组指针括号里为什么是3不是2?
最佳答案
2019-7-22 11:34:40
本帖最后由 neverBingo 于 2019-7-22 11:42 编辑

我想尝试一下回答这个问题。实际上,近期我也在学习C语言,对于其中的指针问题,也在痛苦地理解中。

小甲鱼在课程中,将“数组指针”和“指针数组”两个概念放在一起讲,避免大家混淆。但我在理解的过程中,发现“数组指针”和“指向数组的普通指针”两者更容易混淆。

一、“数组指针”和“指向数组的一般指针”
这两者都是指向数组的(这里是简要地说,更为精确的说法则不是这样),所有两者非常具有迷惑性。让我们来看看他们的定义:
  1. int a[3] = {1, 2, 3};
  2. int (*pa)[3] = &a;    //数组指针
  3. int *pb = a;    //指向数组的一般指针
复制代码

从上面内容看,他们都指向这个数组,使用的时候非常容易混淆。
特别当我们打印地址时:
  1. printf("pa -> %p\n", pa);
  2. printf("pb -> %p\n", pb);
复制代码

pa和pb打印出来的内容,是一样的,这就让我们更难区分他们。

二、他们到底指向的是什么?
从我最近的理解来看,两者从指向的内存的角度来看,还是存在比较大的差异的。
pa是数组指针,他指向的内存地址是从数组的首地址开始的连续3个int内存单元(就是12个字节)。
pb是普通指针,他指向的内存地址是从数组的首地址开始的连续1个int内存单元(就是4个字节)。
以上的差异可以从下面的语句看出来:
  1. printf("pa+1 -> %p\n", pa+1);
  2. printf("pb+1 -> %p\n", pb+1);
复制代码

当我们将指针向数组的尾巴方向移动1个位置时,pa移动的是12个字节,而pb移动的是1个字节。
这样的结果,反映了我前面的理解。

以这样的理解,来看待数组的定义。如果将前面的数组按照如下的方式定义,则更容易看出差异:
  1. int (*pa)[3] = &a;
  2. int *pb = &a[0];
复制代码

你看,数组定义的时候,都是对某一对象进行取址运算,数组指针是对数组进行取址,普通指针是对具体的存储内容进行取址。

三、回到楼主的问题上来
当我们要定义一个数组指针的时候,我们首先要明白,这个指针想指向谁?
以楼主的例子来说,数组array是一个二维数组,第一维包含两个对象,分别是两个数组;第二维前三个是一个数组,后三个又是一个数组,我们把这两个数组暂且称为第二维数组。
如果想指向整个二维数组,就应该定义为(*p)[2][3] = &array
如果想指向两个第二维数组中的第一个,就应该定义为(*p)[3] = &array[0];当然,你也可以指向第二个,(*p)[3] = &array[1]
当指向第一个时,由于array的首地址值恰好就是 &array[0],所以也写成(*p)[3] = array

那么,能不能将指针只指向第一维数组呢,就是能不能写成 (*p)[2] = &array呢?
楼主可以试一试,应该是不能的,因为如果不提供第二维数组中变量的个数,编译过程中无法计算出指针到底要指向多少内存单元。


以上就是我的一点浅见,仅供参考。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-7-21 14:16:24 | 显示全部楼层
暂时理解为列数即可

其实真正的意思是  int(*p)[3]    这个指针指向一个有3个元素的数组
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-7-21 14:46:56 | 显示全部楼层
我叫MD 发表于 2019-7-21 14:16
暂时理解为列数即可

其实真正的意思是  int(*p)[3]    这个指针指向一个有3个元素的数组

谢谢,我不太理解为什么3个元素是指列数而不是行数。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-7-21 17:43:55 | 显示全部楼层
sunxu123 发表于 2019-7-21 14:46
谢谢,我不太理解为什么3个元素是指列数而不是行数。

额 这个问题有些无法回答啊  自己多练练就理解了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-7-21 18:09:02 | 显示全部楼层
  1. int arr1[2] = {100, 101};
  2. int arr2[2][3] = {{102, 103, 104}, {200, 201, 202}};
  3. int arr3[2][4] = {{300, 301, 302, 303}, {400, 401, 402, 403}};
  4. int arr4[3][2] = {{500, 501}, {600, 601}, {700, 701}};

  5. arr1是一个数组,这个数组有2个元素,分别是:100, 101
  6. arr2是一个数组,这个数组有2个元素,分别是:{102, 103, 104}, {200, 201, 202},注意,把大括号看成一个整体,这里有两对大括号,arr2有两个元素
  7. arr3是一个数组,这个数组有2个元素,分别是:{300, 301, 302, 303}, {400, 401, 402, 403}
  8. arr4是一个数组,这个数组有3个元素,分别是:{500, 501}, {600, 601}, {700, 701}

  9. int arr4[3][2];你可以把这个说成是二维数组,也可以说成是数组的数组,就是数组中存储的是数组

  10. int arr5[3]; 数组中存储的是int
  11. int arr6[3][2];数组中存储的是数组,存储了一个有两个元素的数组
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-7-22 11:15:16 | 显示全部楼层
本帖最后由 sunxu123 于 2019-7-22 11:17 编辑


谢谢。
但是按照前面说的,这个arr6[3][2]和arr4[3][2]不都应该是3个元素么,那就是说arr6有3个数组组成,每个数组有2个元素。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-7-22 11:34:40 | 显示全部楼层    本楼为最佳答案   
本帖最后由 neverBingo 于 2019-7-22 11:42 编辑

我想尝试一下回答这个问题。实际上,近期我也在学习C语言,对于其中的指针问题,也在痛苦地理解中。

小甲鱼在课程中,将“数组指针”和“指针数组”两个概念放在一起讲,避免大家混淆。但我在理解的过程中,发现“数组指针”和“指向数组的普通指针”两者更容易混淆。

一、“数组指针”和“指向数组的一般指针”
这两者都是指向数组的(这里是简要地说,更为精确的说法则不是这样),所有两者非常具有迷惑性。让我们来看看他们的定义:
  1. int a[3] = {1, 2, 3};
  2. int (*pa)[3] = &a;    //数组指针
  3. int *pb = a;    //指向数组的一般指针
复制代码

从上面内容看,他们都指向这个数组,使用的时候非常容易混淆。
特别当我们打印地址时:
  1. printf("pa -> %p\n", pa);
  2. printf("pb -> %p\n", pb);
复制代码

pa和pb打印出来的内容,是一样的,这就让我们更难区分他们。

二、他们到底指向的是什么?
从我最近的理解来看,两者从指向的内存的角度来看,还是存在比较大的差异的。
pa是数组指针,他指向的内存地址是从数组的首地址开始的连续3个int内存单元(就是12个字节)。
pb是普通指针,他指向的内存地址是从数组的首地址开始的连续1个int内存单元(就是4个字节)。
以上的差异可以从下面的语句看出来:
  1. printf("pa+1 -> %p\n", pa+1);
  2. printf("pb+1 -> %p\n", pb+1);
复制代码

当我们将指针向数组的尾巴方向移动1个位置时,pa移动的是12个字节,而pb移动的是1个字节。
这样的结果,反映了我前面的理解。

以这样的理解,来看待数组的定义。如果将前面的数组按照如下的方式定义,则更容易看出差异:
  1. int (*pa)[3] = &a;
  2. int *pb = &a[0];
复制代码

你看,数组定义的时候,都是对某一对象进行取址运算,数组指针是对数组进行取址,普通指针是对具体的存储内容进行取址。

三、回到楼主的问题上来
当我们要定义一个数组指针的时候,我们首先要明白,这个指针想指向谁?
以楼主的例子来说,数组array是一个二维数组,第一维包含两个对象,分别是两个数组;第二维前三个是一个数组,后三个又是一个数组,我们把这两个数组暂且称为第二维数组。
如果想指向整个二维数组,就应该定义为(*p)[2][3] = &array
如果想指向两个第二维数组中的第一个,就应该定义为(*p)[3] = &array[0];当然,你也可以指向第二个,(*p)[3] = &array[1]
当指向第一个时,由于array的首地址值恰好就是 &array[0],所以也写成(*p)[3] = array

那么,能不能将指针只指向第一维数组呢,就是能不能写成 (*p)[2] = &array呢?
楼主可以试一试,应该是不能的,因为如果不提供第二维数组中变量的个数,编译过程中无法计算出指针到底要指向多少内存单元。


以上就是我的一点浅见,仅供参考。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2019-7-22 11:46:44 | 显示全部楼层
本帖最后由 neverBingo 于 2019-7-22 11:48 编辑

上面的回帖中未定的内容,我尝试了一下:
“那么,能不能将指针只指向第一维数组呢,就是能不能写成 (*p)[2] = &array呢?
楼主可以试一试,应该是不能的,因为如果不提供第二维数组中变量的个数,编译过程中无法计算出指针到底要指向多少内存单元。”

实际上,可以通过编译,但是会报警。

而且,我还把指针移动了一个位置,发现内存指向移动了8个字节。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-7-22 14:32:06 | 显示全部楼层
neverBingo 发表于 2019-7-22 11:34
我想尝试一下回答这个问题。实际上,近期我也在学习C语言,对于其中的指针问题,也在痛苦地理解中。

小 ...

解释的很清楚,非常感谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-25 01:17

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表