c - 为什么我可以从 int**(作为二维数组)转换为 int*?
问题描述
我写了代码 -
int arr2d[2][2] = {{1, 2}, {3, 4}};
int * arr = (int*)arr2d;
int i = 0;
for(i = 0; i < 4; i++)
{
printf("%d ", arr[i]);
}
输出就好像我在 arr2d 中打印了数组中的每个元素,没有什么不寻常的。为什么呢?
解决方案
为什么我可以从 int**(作为二维数组)转换为 int*?
你有一个误解。 数组不是指针。在大多数情况下,它们确实会衰减为指针,但这是评估问题,而不是自然问题。因此,二维数组是数组的数组,而不是指针的数组。因此,它们不会衰减为指向指针的指针,而是指向数组的指针。您的代码中没有int**
任何地方涉及。
鉴于此声明:
int arr2d[2][2] = {{1, 2}, {3, 4}};
您可以在没有强制转换的情况下执行的相关指针分配是
int (*arr2d_ptr)[2];
arr2d_ptr = arr2d; // arr2d is not a pointer, but it does decay to one in this expression
arr2d_ptr
是一个指向 的二元素数组的指针int
。赋值使它指向 的第一个元素arr2d
。如果将其转换为 type int *
,则结果指向int
数组中的第一个arr2d_ptr
指向的对象。例如,
int *ip = (int *) arr2d_ptr;
这很自然,因为这int
正是数组的第一部分。您可以通过索引作为ip[0]
或访问它*ip
。您可以int
将该数组中的第二个访问为ip[1]
.
我想问题的另一个方面是关于表达式ip[2]
和ip[3]
. 数组是元素的连续序列。数组的数组在这方面并不特殊:它们是(较小的)数组的连续序列。因此,您的布局arr2d
是这样的:
array..|array..|
. 如果你覆盖每个成员数组的布局,那么你会得到:
int|int|int|int|
,这与四个 的一维数组的布局完全相同int
。这就是为什么您可以int
通过索引ip
(或arr
在您的示例代码中)访问所有四个 s。
有趣的事实:因为数组类型的表达式衰减为指针,所以这里不需要强制转换。您可以改为取消引用 arr2d_ptr
以形成一个表达式,指定 2D 数组的第一个元素,这是一个 1D 数组,并让它衰减到一个指针:
int *ip2 = *arr2d_ptr;
或者,等效地,
int *ip3 = *arr2d;
推荐阅读
- javascript - React:更新状态变量的简写
- docker - 在 docker 容器中构建项目并在挂载中共享文件夹
- r - 将整数转换为日期
- uwp - 基于 UWP 应用最低版本的安装限制
- couchbase - 使用 cbbackup 在 couchbase 中进行备份时出现异常
- rabbitmq - RabbitMQ — 为什么在使用主题交换时我的路由键被忽略
- c# - 控制器 ASP.net 核心 2.1 中的 Jwt 角色身份验证
- java - 依次打印 ArrayList 中的所有字符
- c# - 访问 CommandParameter 字段 (c# Xamarin)
- opengl - OpenGL3中的虚线?