在 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 ++中将int数组转换为字节数组[重复]

无法在赋值c ++中将char *转换为int * [关闭]

在 C++ 中将 bitset 转换为 int

c++ 不使用 C 标准库将字符串和 int 转换为 char*

如何在 C++ 中将字符串转换为 int?