clang ++无法使用类型为'int(*)[dim2]'的右值初始化'int(*)[dim2]'类型的变量

时间:2015-01-22 16:49:20

标签: c++

为什么代码

void fcn(int *twoDArrayPtr, const int dim1, const int dim2) {
    int (*array)[dim2] = reinterpret_cast<int (*)[dim2]>(twoDArrayPtr);
}

int main() {
    return 0;
}

生成编译器错误

error: cannot initialize a variable of type 'int (*)[dim2]' with
  an rvalue of type 'int (*)[dim2]'

类型是相同的,所以我认为可以执行任务。由于int (*)[dim2]是一个指向大小为dim2的数组的指针,因此可能是一个指向一堆大小为dim2的数组的指针,这些数组在指针可索引的连续内存中,我会认为这应该工作。

我在Mac OS / X上使用clang ++,其中包含以下版本信息:

Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.0.0
Thread model: posix

3 个答案:

答案 0 :(得分:2)

dim2不是编译时常量,并且在C ++中不存在VLA(可变长度数组)。其他一些编译器(如gcc)具有语言扩展,允许在C ++中使用VLA,但clang的行为符合标准。

您可以使用为您执行地址转换的类(或类模板)来解决此问题,例如

// This is very rudimentary, but it's a point to start.
template<typename T>
class array2d_ref {
  public:
    array2d_ref(T *p, std::size_t dim) : data_(p), dim_(dim) { }

    T *operator[](std::size_t i) { return &data_[i * dim_]; }

  private:
    T *data_;
    std::size_t dim_;
};

...

array2d_ref<int> array(twoDArrayPtr, dim2);

但我担心除非你在编译时知道数组的维度,否则不可能(可移植地)拥有指向数组的指针。

答案 1 :(得分:1)

当您在演员表中使用dim2作为数组维度时,您尝试使用C99的可变长度数组(VLA)功能。 (例如,gcc支持扩展名:https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html。)

好消息,你现在不能这样做,但是你很快就可以引入C++14's Runtime Sized Arrays

有关引言:

  

运行时大小的数组提供与C99的VLA相同的语法和性能......请记住,运行时大小的数组与C99的VLA并不完全相同。 C ++ 14功能更加内敛,同样也是如此。具体而言,排除以下属性:

     
  • 运行时大小的多维数组
  •   
  • 对函数声明符语法的修改
  •   
  • sizeof(a)是运行时评估的表达式,返回
  • 的大小   
  • typedef int a[n];评估n并将其传递给typedef

所以你的代码很快就会合法,大约是C ++ 14。

我已经在Visual Studio 2015测试版上试用了它,遗憾的是在撰写本文时它不受支持:(

答案 2 :(得分:0)

虽然clang不支持可变长度数组,但有一种解决方法。以下用clang ++ 4.0.0编译:

void fcn(int *twoDArrayPtr, const int dim1, const int dim2) {
    using array_type = int (*)[dim2];
    array_type array = reinterpret_cast<array_type>(twoDArrayPtr);
}

int main() {
    return 0;
}

我不确定为什么这个别名声明应该有所不同。这看起来肯定不一致。