将 int** 转换为"pointer to a two-dimensional array of integers with fixed number of elements per column"

Casting int** to the "pointer to a two-dimensional array of integers with fixed number of elements per column"

本文关键字:of integers fixed with elements column per number two-dimensional 转换 int      更新时间:2023-10-16

假设有一个 int** 类型的变量,它是指向 5x5 2D 数组的指针:

int** ptr_array_5by5;

以及具有以下原型的函数:

void print2DArray_with5Columns(int (*ptr_row)[5]);

有没有办法将ptr_array_5by5转换为某种与函数的第一个参数的类型匹配的类型?

print2DArray_with5Columns( (<some casting type>) ptr_array_5by5)

这里要意识到的重要一点是,int**不是指向任何内容的 2D 数组的指针。 它是指向 1D 的指针指针数组。 int (*)[5] 是指向 2D 数组的指针 int(或者更准确地说,它是指向第一个元素的指针(这样的数组(。 您几乎可以转换任何指针类型到任何其他使用 reinterpret_cast 的指针类型,但它是也几乎保证在运行时不起作用。 (有特殊例外,但它们都是特定于平台的,并且非常靠近硬件。

如果你真的有一个指向 5 int*int**,每个这指向 5 int,你需要一个int (*)[5],唯一的您将能够成功转换的方法是通过对实际基础数据的转换(这将涉及副本(,而不是指针上的转换。 像这样:

int tmp[5][5];
for ( int i = 0; i != 5; ++ i ) {
    int* row = ptr_array_5by5[i];
    for ( int j = 0; j != 5; ++ j ) {
        tmp[i][j] = row[j];
    }
}

然后,您可以在没有任何强制转换的情况下将tmp传递给您的函数:数组到指针的隐式转换将转换 int [5][5] int (*)[5] .

当然。

int** ptr_array_5by5;  
void print2DArray_with5Columns(int (*ptr_row)[5]);
print2DArray_with5Columns( (int (*)[5]) ptr_array_5by5);
print2DArray_with5Columns( reinterpret_cast<int (*)[5]>(ptr_array_5by5));

C 语言声明语法(尽管存在所有错误(允许您通过简单地重写声明而省略任何标识符来创建强制转换。它可以编译,甚至可能工作。


这里有很多混淆,因为描述性措辞与 C 声明不匹配。正如我所说,这里有一些实现这种(特殊(强制转换的代码,并表明它可以工作。

void print2DArray_with5Columns(int (*ptr_row)[5]) {
    for (int i = 0; i < 5; i++)
        cout << (*ptr_row)[i] << " ";
    cout << std::endl;
}
int main() {
    int* a;
    int** ptr_array_5by5;
    a = new int[25];
    for (int i = 0; i < 25; i++)
        a[i] = i;
    ptr_array_5by5 = (int**)a;
    print2DArray_with5Columns((int (*)[5])(ptr_array_5by5));
    return 0;
}

请注意,此声明不是 5x5 矩阵。强制转换只是指向 5 个整数的数组的指针,该数组衰减为一个简单的数组。此代码生成一个 5x5 平面矩阵并打印第一行。

我怀疑真正的问题是演员是错误的,因此整个问题都是错误的。


有人问这是否是可怕的未定义行为。如果照顾得当,则不是。实际上,该标准允许将任何类型的指向对象的指针强制转换为其他指向对象的指针或 void 指针或足够大的整数,然后再返回。[指针到函数和指针到成员的处理方式略有不同。回合跳闸指针保证保持相同的值。因此,只要遵循规则,这种强制转换就不是UB,这并不难做到。

  1. int**int(*)[5]是不同的类型(正如N.M.指出的那样(
  2. 您可以将数组视为指针,例如 int a[5]; *(a+1) = 6;
  3. 您可以将指针视为数组,例如 int *a = new int[5]; a[1] = 6; .

但是,将对象 A 视为对象 B 并不意味着它实际上是对象 B。

不过,您可以做的是声明一个int (*)[5],将ptr_array_5by5的值写入其中(当然是在分配内存之后(,然后将其传递给print2DArray_with5Columns

另一方面,是的,有一些强制转换可以使您的代码编译。但我怀疑使用其中之一是否能让你更接近你的目标(见 http://ideone.com/lVzNrN(。

我认为您对假设指针是数组感到困惑。指针不是数组,反之亦然。如果ptr_array_5by5是一个 2D 数组,那么原型中的参数可以作为参数传递ptr_array_5by5。但是您将其声明为 int **ptr_array_5by5 ,最好将参数更改为int **类型。

为什么要投射 int **?

您可以使用指针指向地址。

因此,您必须将此指针

指向某个变量,而不是类型转换指针。

类型转换指针没有任何意义,因为它们本身不存储值。