八义士 发表于 2024-8-27 10:52:50

新手学二维数组指针



一维数组中:a和*(a+i)都是表示一维数组中的第i个元素,*作用是取值。


二维数组中:a和*(a+i), 都是表示第i行0列元素地址,后者的*为啥作用不是取值啦{:5_99:}

各位鱼友,老师,这该怎么看

FishC 发表于 2024-8-27 10:52:57

你好,鱼油!

二维数组确实有点让人困惑。让我来简洁地解释一下。

假设有一个二维数组 `int a`,数组有3行4列。

- `a`:表示整个二维数组的首地址,即 `a` 的地址。
- `a + i`:表示第 i 行的地址,也就是 `a` 的地址。
- `*(a + i)`:解引用后,表示第 i 行的首地址,也就是 `a` 的首地址,实际是 `a`。

对于二维数组的指针操作:

1. `a` 是二维数组的名字,作为一个指针常量,它指向的是整个数组 `a` 的地址。
2. `a + i` 是在 `a` 的基础上偏移了 `i` 行,它指向第 `i` 行的首地址,即 `a`。
3. `*(a + i)` 是对 `a + i` 解引用,等同于 `a`,表示第 `i` 行的首地址。

所以,在二维数组中,`a` 和 `*(a + i)` 并不是表示同一个内容,前者是整个数组首地址,而后者是第 `i` 行的首地址。如果我们想取第 i 行第 j 列的元素,可以用 `*(*(a + i) + j)`,也就是 `a`。

希望这能帮助你理解!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

八义士 发表于 2024-8-27 10:56:09

FishC 发表于 2024-8-27 10:52
你好,鱼油!

二维数组确实有点让人困惑。让我来简洁地解释一下。


`*(a + i)`:解引用是什么意思

FishC 发表于 2024-8-27 10:56:19

八义士 发表于 2024-08-27 10:56
`*(a + i)`:解引用是什么意思

你好,鱼油!

“解引用”是指通过指针访问指针所指向的对象的值。让我们详细解释一下你提到的情况:

假设有一个二维数组 `int a`,这个数组有3行4列。

- `a` 是一个指向包含4个整数的一维数组的指针。
- `a + i` 是指向第 `i` 行的指针。具体地说,`a + i` 是 `a` 的第 `i` 个元素的地址,也就是第 `i` 行的首地址。

那么,`*(a + i)` 怎么理解呢?

1. `a + i` 给我们的是第 `i` 行的首地址。
2. 通过 `*` 操作对 `a + i` 进行解引用,我们得到第 `i` 行这一整行(实际上是一个指向第 `i` 行第一个元素的指针)。

所以,`*(a + i)` 代表的是第 `i` 行的首地址,即 `a`。

举个例子:假如我们有一个二维数组 `a`,如下所示:
int a = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

我们来理解具体的操作:
- `a` 是二维数组名字,指向数组首地址。
- `a + 1` 是二维数组 `a` 的第 1 行的首地址(即指向 `{5, 6, 7, 8}` 的首地址)。
- `*(a + 1)` 对第 1 行首地址进行解引用,得到的就是这行首地址对应的数组 `{5, 6, 7, 8}`。

这么一来,通过 `*(a + i)` 解引用的结果,可以使用索引操作,来取具体的值,比如 `*(*(a + 1) + 2)` 等于 `7`。

希望这一解释更加清晰,帮助你理解二维数组指针的解引用!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

jackz007 发表于 2024-8-27 16:25:44

本帖最后由 jackz007 于 2024-8-27 18:06 编辑

    对于指针而言,最重要的是必须弄清楚一个表达式究竟是一个指针还是一个数组元素。
    例如:
    对于一维数组
char p ;
    p 是个一级指针(char *),* (p + i)不再是任何指针,而是一个数组元素(char) p 。

    对于二维数组
char q ;
    q 是个二级指针(char **),* (q + i)是一个一级指针(char *) ,* ( * (q + i) + j) 不再是任何指针,而是一个数组元素(char) q 。

    对于三维数组
char r ;
      r 是个三级指针(char ***),* (r + i)是一个二级指针(char **) ,* ( * (r + i) + j) 是一个一级指针(char *),* (* ( * (r + i) + j) + k) 不再是任何指针,而是一个数组元素(char) r 。

      【总结】:
char r ;
/*
         r : 三级指针
         * r :二级指针 r
      ** r :一级指针 r
       *** r :数组元素 r
*/
   

zhouzihang 发表于 2026-1-17 16:11:06

{:5_95:}

xiaotubie 发表于 2026-4-5 10:15:07

本帖最后由 xiaotubie 于 2026-4-9 14:33 编辑

如果a是数组,那么a和*(a+i)都是获取数组的第i个元素,并不是取地址。当a是二维数组,你打印出来是地址,是因为数组对象在表达式中会隐式转换为首元素指针

看下面的代码,我故意用匿名数组,防止有人说数组名就是指针这种错误的说法,数组名肯定是代表的数组,切记!

   printf("0号子数组的地址:%p,0号子数组的大小:%zu\n", (int) { 1, 2, 3,4,5,6 } , sizeof ((int) { 1, 2, 3, 4, 5, 6 }));
   printf("0号子数组的地址:%p,0号子数组的大小:%zu", *(int) { 1, 2, 3, 4, 5, 6 }, sizeof *(int) { 1, 2, 3, 4, 5, 6 });



二维数组不管用[ ]还是*运算符,得到的其实都是子数组,只不过表达式中它隐式转换为了首元素指针(地址),你看着以为得到的是地址
一维数组[]和*运算符得到的是子元素int对象,不存在隐式转换,所以看到就是元素值

一个int类型的a和float类型的b 相加,a会隐式转换成float类型,这个隐式转换我们无法直接看见,但你不能说a就是float类型

很多人错误的认为一维数组名就是一级指针二维数组名就是二级指针,如果它真是一个指针 当你sizeof的时候得到的应该是一个地址大小   而不是数组的大小,而他们还认为这是特殊情况。
编程语言中,有各种数据类型的对象,我们给对象创建了一个名字来代表。数组就是一些同类型数据按一定顺序排列起来的集合,取一个名字,数组名。而有些人却说它不表示数组,表示指针,数组和指针都不是一个东西。
C语言中 用指针来表示某种类型数据的地址,如果知道数组的地址,就可以很好的使用它了。但是怎么把数组和地址关联起来,使用又方便呢?因此约定,如果需要访问数组数据时,让数组对象直接隐式转换为首元素的指针。
而且其实下标运算符[ ] 也是指针运算符(不是数组),是*运算符的一种简便书写方式,因为存在数组对象到指针的隐式转换,所以也可以写   数组对象 。这个数组对象可以匿名的,也可以带名字的(数组名)



页: [1]
查看完整版本: 新手学二维数组指针