在 C / C++ 中将 int* 转换为 int(*)[n]
Posted
技术标签:
【中文标题】在 C / C++ 中将 int* 转换为 int(*)[n]【英文标题】:Convert int* to int(*)[n] in C / C++ 【发布时间】:2019-08-07 09:32:44 【问题描述】:如何将指针转换为“指向数组的指针”?
例如,假设我有一个指针 int *data
指向某个 15 个整数的内存块。我想做类似的事情:
int (*mat)[5] = data;
所以我现在可以制作:
for(int i = 0; i < 3; i++)
for(int j = 0; j < 5; j++)
mat[i][j] = // Something.
但是,我收到 gcc 警告:
warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
int (*mat)[5] = data;
和 g++ 的错误:
error: cannot convert ‘int*’ to ‘int (*)[5]’ in initialization
int (*mat)[5] = data;
如果我添加一个显式转换 int (*mat)[5] = (int (*)[5])data;
它编译时没有警告,但我不知道这是否会产生未定义的行为。
实现此目的的正确方法是什么?可以在没有明确演员表的情况下制作吗?
编辑:
我知道我可以像这样使用int *
指针:
data[5*i + j] = \\ Something.
但在我的实际情况下,我需要通过 3 个维度迭代数组,
[]
中的代码很长,这就是我想使用
mat[i][j]
符号。
【问题讨论】:
相关:C++ Multidimensional array in existing memory 也许将数组作为void*
传递?见ideone.com/zOeKcE
你不能直接使用int **
而不是int *
吗?这样您就可以使用[][]
语义。一个简单的int *
做不到。如果你真的想转换它,你需要创建一个int **
并根据你需要的矩阵尺寸复制int *
的内容。
没有像 C/C++ 这样的语言。你需要选择一个。无论如何要问一个问题。
【参考方案1】:
我认为将指针转换为数组指针并随后使用它不应该是 UB,而且它在技术上不是,只要指针指向的空间足够大。
只要您满足目标对齐要求,指针转换就不是 UB。如果违反严格的别名规则,指针解引用可能是 UB。然而,数组指针的警告是,严格的别名规则只涉及通过给定类型的左值进行的访问,并且您永远不能使用数组类型的左值进行访问——您总是最终访问,大概正确键入的单个元素。
尽管如此,我认为在这种情况下,显式指针算法可能更可取。它显然是无 UB 的,并且它避免了指针强制转换,这通常很危险,并且可以说对大多数 C/C++ 程序员来说应该看起来很刺耳。
【讨论】:
严格的别名规则说“一个对象的存储值只能由具有以下类型之一的左值表达式访问:... - 包括上述之一的聚合或联合类型其成员之间的类型”因此涵盖了数组情况,数组是聚合类型。 我可以假设int[m][n]
与int[m*n]
具有相同的内存表示吗?
@Sergio 是的。数组未填充。查看***.com/questions/1066681/…【参考方案2】:
int (*mat)[5] = (int (*)[5])data;
很好,因为实际存储在那里的是一个 int[5]
数组,仅此而已。 C 只关心对象在内存中的有效类型。
要在没有显式强制转换的情况下执行此操作,您必须进行一些联合黑客攻击,这仅在 C 中有效,在 C++ 中无效:
typedef union
int* ptr;
int(*arr)[5];
arr_t;
int (*mat)[5] = (arr_t) .ptr = data .arr;
但这并不能完全提高可读性,所以我不推荐它。请改用演员表。
【讨论】:
以上是关于在 C / C++ 中将 int* 转换为 int(*)[n]的主要内容,如果未能解决你的问题,请参考以下文章
在 C 和 C++ 中将 int 值转换为 char 指针差异
无法在赋值c ++中将char *转换为int * [关闭]