arrays - 在多维数组引用期间,解引用运算符告诉编译器做什么?
问题描述
我一直在玩多维数组和括号表示法,尽我所能对解引用、指针类型和指针算术之间的相互作用提出概念上的理解。
对于这个问题,请考虑以下任意 3D 数组引用:
arr[i][j][k]
现在,我相信以下转换是等效的(我运行了一些我认为可以确认准确性的代码示例):
*(*(*(arr+i)+j)+k)
我运行的代码如下所示:
#include <stdio.h>
int main(void) {
char arr[2][3][4] = { 'a', 'b' ,'c' ,'d' ,'e' ,'f' ,'g' ,'h' ,'i' ,'j' ,'k' ,'l' ,'m' ,'n' ,'o' ,'p' ,'q' ,'r' ,'s' ,'t' ,'u' ,'v' ,'w' ,'x' };
printf("%c \n", arr[1][1][1]);
printf("%c \n", *(*(*(arr+1)+1)+1));
return 0;
}
您可以更改printf
语句中的值(只要i
、j
和的值k
在两者之间相同)。无论如何,他们总是同意将什么字母打印到命令终端。
我获得这个假定的等效答案的方式如下图所示(对不起,我使用了数学堆栈交换编写软件,因为它使一切变得更容易......如果指针算术的符号有点混乱,我很抱歉.)
所以我的主要困惑来自取消引用运算符*
。坦率地说,我不明白它告诉编译器做什么。
举个简单的例子,假设字符数组arr
从基地址 100 开始。
arr
实际上是一个指向类型为 2D 矩阵的指针char[3][4]
。我相信这意味着(因为一个字符需要 1 个字节)代码arr + 1
实际上是在说100+12
. 重写我的方程,然后我会:
*(*(*(112)+1)+1)
. 我相当确定取消引用运算符(在 的左侧112
)从左到右优先于+
符号(在 的右侧112
)。
根据我在 1D 情况下使用取消引用符号的经验,这将产生存储在 112 存储单元中的值。但这在目前的情况下似乎是错误的。显然,我不了解取消引用操作在这种情况下的行为方式。任何帮助是极大的赞赏!
干杯~
解决方案
您需要了解两点:
数组不是指针,即使在大多数情况下它们会自动转换为指针。
与一维数组相比,多维数组得到零特殊处理。它们是一维数组,其中每个元素也是一个数组。
当您这样做时*(*(*(arr+1)+1)+1)
,arr
会自动转换为指向其第一个元素的指针。该指针具有类型char(*)[3][4]
(指向 的指针char[3][4]
)。添加1
它会使指针的值增加1*sizeof(char[3][4]) == 12
. 你似乎已经知道这一点。
取消引用生成的指针会给你一个类型的左值char[3][4]
,然后它会衰减为类型char(*)[4]
等于的指针&arr[1][0]
。添加1
到该指针会使它增加1*sizeof(char[4])
,之后它等于&arr[1][1]
。
取消引用结果指针会为您提供 type 的左值char[4]
。它还衰减为类型char *
等于的指针&arr[1][1][0]
。添加1
到它之后,它的值增加1*sizeof(char)
并变为等于&arr[1][1][1]
。然后最后的取消引用给你的值arr[1][1][1]
。
推荐阅读
- javascript - 如何将 document.body.appendchild(' 定位到根文档而不是 iframe
- javascript - 在选择更改时打开一个新标签 - 仅适用于 Chrome
- java - 使用 parentId 将子关系设置为父级,并在一个事务中获取列表中所有子级的父级
- java - XML 签名的引用中的 DigestValues 来自哪里?
- python - 使用外键批量插入行并自动将行添加到引用的表中
- sql-server - 使用 (.dtsConfig) 文件将 SSIS 部署到目录
- javascript - 引导工具提示和选择下拉重叠问题
- jenkins - 如何在 Jenkins 中使用 configuration-as-code 插件配置 config-file-provider 文件
- entity-framework - 使用 EF Core 记录查询持续时间
- directory - 如何在 Centos7 中查看超过 700 万个 tiff 文件的文件夹的内容?