转换为指向运行时确定大小的数组的指针

Posted

技术标签:

【中文标题】转换为指向运行时确定大小的数组的指针【英文标题】:Cast to pointer to array of runtime-determined size 【发布时间】:2018-03-17 05:11:23 【问题描述】:

C++ 标准是否允许这种转换?我能够使用 g++ 5.4(在 linux 中运行)编译它,但不能使用 g++ 4.2(在 OSX 中运行)。

char* ptr;
char (*img)[width][3] = (char (*)[width][3])ptr;

'width' 是在运行时确定的整数。 g++ 4.2 抛出:

cannot initialize a variable of type 'char (*)[width][3]'
  with an rvalue of type 'char (*)[width][3]'

这对我来说没有任何意义。

(PS:第一次编译时我真的很惊讶)

编辑

g++5.4编译的小代码

#include <iostream>
int main()
    char* ptr;
    int width;
    std::cin >> width;
    char (*img)[width][3] = (char (*)[width][3])ptr;

无法用 g++4.2 编译的 Mac 现在不在我身边,所以我无法重现错误。如 @xskxzr 与 Compiler Explorer 的 cmets 所示,it compiles in g++4.1。但是,it doesn't compile in clang,抛出了我之前说的同样的错误:

<source>:9:12: error: cannot initialize a variable of type 'char (*)[width][3]' with an rvalue of type 'char (*)[width][3]'
    char (*img)[width][3] = (char (*)[width][3])ptr;
           ^                ~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
Compiler returned: 1

问题是:

如何解释输出错误?

g++ 版本是否可能与 OSX 完全不同?

【问题讨论】:

它 can compile 即使使用 gcc 4.1.2。 gcc 支持可变长度数组作为扩展功能。我猜您已经使用了一些命令选项来禁用此功能。此外,即使支持变长数组,由于严格的别名规则,转换仍然是未定义的行为。 我们可以有一段代码可以实际编译吗?以上内容当然不在 gcc g++ 7.0 中,在 clang 中也没有 我刚刚编辑并添加了完整的代码。 @xskxzr 我不知道严格的别名规则,我只是读了一点。据我了解,如果您有指向同一内存的不同类型的指针,编译器优化可能会搞砸,对吗? PS:我很确定我在那个 g++4.2 上没有任何特殊的命令选项 【参考方案1】:

Mac 上的编译失败可能是由于 Clang 错误(所以 g++ 在那里运行 Clang,而不是 GCC)。之前观察过:

Issue with variable length arrays and C++: differences between g++ and clang

可变长度数组是对 C++ 的 GNU 扩展,Clang 也应该支持它。

至少在某些版本的 Clang 中,可以通过为可变长度数组类型引入显式 typedef 来编译它:

typedef int (*vla)[width][3];
vla img = (vla) ptr;

【讨论】:

很好的答案。我不明白你所说的“g++ ran clang”是什么意思。他们不是两个不同的编译器吗? Apple 只发布了一个非常旧的 GCC 版本,它不再很有用了。显然,有一个工具链选择工具xcode-select 控制调用g++ 时运行的内容。 (我不是 Mac 用户。)

以上是关于转换为指向运行时确定大小的数组的指针的主要内容,如果未能解决你的问题,请参考以下文章

指针与数组

关于如何定义一个未知大小的数组

malloc如何在编译时和运行时处理? [关闭]

如何将简单指针转换为固定大小的多维数组?

程序的错误输出,使用指向结构数组的指针

在没有向量、指针的情况下在 C++ 中在运行时增加数组大小 [关闭]