简体   繁体   English

C++ 中数组大小未知的指针转换

[英]Pointer casting with unknown array size in C++

how can I cast void pointer to a 2d array (array of pointers to arrays of ints), when I dont know array size at compile time?当我在编译时不知道数组大小时,如何将 void 指针转换为二维数组(指向整数的 arrays 的指针数组)? Is it somehow possible?有可能吗? (I am doing this because, I pass an 2d array of unknow size to a func. So I cast 2d array to a void pointer and then in that func I want it to recast back.) (我这样做是因为,我将一个未知大小的二维数组传递给一个函数。所以我将二维数组转换为一个 void 指针,然后在那个函数中我希望它重新转换回来。)

int i = 5;

int tab1[i][i];

//cast to void pointer
void *p = (void *)tab1;

//and recast back
int (*tab2)[5] = (int (*)[5])p;   //this is working
int (*tab3)[i] = (int (*)[i])p;   // but this is not

First I suggest to don't use runtime size for array in C/C++, except you using STL vector as an array.首先,我建议不要在 C/C++ 中对数组使用运行时大小,除非您使用 STL 向量作为数组。 so instead of:所以而不是:

int i = 5;

you must use:你必须使用:

const int i = 5;

except you use Vector that is safe and better than intrinsic arrays.除非您使用比固有 arrays 更安全且更好的 Vector。

how can I cast void pointer to a 2d array (array of pointers to arrays of ints), when I dont know array size at compile time?当我在编译时不知道数组大小时,如何将 void 指针转换为二维数组(指向整数的 arrays 的指针数组)? Is it somehow possible?有可能吗?

If we talk about C intrinsic array, It is not possible!如果说C内在数组,那是不可能的!

why it is not possible?为什么不可能? because C/C++ compiler not aware of your the array size, borders,.... so if you cast your 2d array to 1d array, it is possible.因为 C/C++ 编译器不知道您的数组大小、边框......所以如果您将 2d 数组转换为 1d 数组,这是可能的。 it is the reason that tab2 array can access to first 5th element of your array.这就是tab2数组可以访问数组的第 5 个元素的原因。 really C/C++ compiler cannot distinguish the different of真的 C/C++ 编译器无法区分

int a[3][3]

with

int a[3*3]

so You must be aware of at least one dimension of your array:所以您必须知道数组的至少一维:

int main() {
    const int i = 3,j = 4;

    int tab1[i][j] = {1,2,3,4,5,6,7,8,9,10,11};

//cast to void pointer
    void *p = (void *)tab1;

    auto a = (int (*)[i][12/i])p;
    return 0;
}

In the above example, I aware about i and total count( 12 ) and I calculate the second dimension.在上面的例子中,我知道i和 total count( 12 ) 并且我计算了第二个维度。 I use auto keyword that very easily inferred the data type.我使用很容易推断数据类型的 auto 关键字。

  1. int i = 5; int tab1[i][i]; is a VLA .是一个VLA It's not standard C++ and should be avoided.它不是标准的 C++,应该避免。

  2. An array-of-pointers-to-arrays (and vector-of-vectors) won't be as efficient as a true 2D array since it's no longer contiguous ( int tab1[5][5] is a true 2D array and is stored contiguously in memory, but the dimensions must be known at compile-time).指向数组的指针数组(和向量的向量)不会像真正的 2D 数组那样有效,因为它不再是连续的( int tab1[5][5]是真正的 2D 数组并且是连续存储在 memory 中,但必须在编译时知道尺寸)。

  3. You can easily create a custom 2D container class that would store the data in a contiguous 1D vector and apply some simple math ( x + y*width ) to access the elements.您可以轻松创建自定义 2D 容器 class ,它将数据存储在连续的 1D vector中,并应用一些简单的数学运算 ( x + y*width ) 来访问元素。

Example:例子:

class Matrix {
    std::vector<int> data;
public:
    const int width;
    const int height;

    Matrix(int width, int height) : width(width), height(height), data(width*height) {}

    int operator()(int x, int y) const {
        return data[y * width + x];
    }

    int& operator()(int x, int y) {
        return data[y * width + x];
    }

};

void print(Matrix const& mat) {
    for (int y = 0; y < mat.height; y++) {
        for (int x = 0; x < mat.width; x++)
            std::cout << mat(x, y) << " ";
        std::cout << std::endl;
    }
}

int main() {
    Matrix mat(5, 5);
    mat(1, 1) = 1;
    mat(2, 2) = 2;
    mat(3, 3) = 3;

    print(mat);
}

For convenience this overloads the () operator.为方便起见,这重载了()运算符。 It's still possible with the [] operator but that will require a proxy class to access the inner dimension(s) and also putting y before x since the dimensions are actually reversed. []运算符仍然可以使用,但这需要代理 class 来访问内部维度,并且还要将y放在x之前,因为维度实际上是相反的。

int tab1[i][i]; is a non-standard compiler extension for variable length arrays.是可变长度 arrays 的非标准编译器扩展。 It is better to avoid this because it is not portable and hard to deal with as you are seeing.最好避免这种情况,因为它不便携且难以处理,如您所见。 You would be better with:你会更好:

std::vector<std::vector<int>> tab1(i, std::vector<int>(i));

Then your function can simply take this vector:那么您的 function 可以简单地采用这个向量:

void foo(const std::vector<std::vector<int>>& array) { ....

how can I cast void pointer to a 2d array (array of pointers to arrays of ints), when I dont know array size at compile time?当我在编译时不知道数组大小时,如何将 void 指针转换为二维数组(指向整数的 arrays 的指针数组)?

You can't.你不能。 You can only cast to a type that is known at compile time.您只能强制转换为编译时已知的类型。

What you can do is convert to a pointer to first element of the first row: int* p = static_cast<int*>(tab1);您可以做的是转换为指向第一行第一个元素的指针: int* p = static_cast<int*>(tab1); . . You can then treat the array as one dimensional 1 .然后,您可以将数组视为一维1 Converting two dimensional indices to one dimensional requires some trivial math: x, y -> x + y * i .将二维索引转换为一维需要一些简单的数学运算: x, y -> x + y * i


1 As long as you don't mind the technicality that pointer arithmetic across the sub array boundary might technically not be allowed by the standard. 1 只要您不介意跨子数组边界的指针算术在技术上可能不被标准允许的技术性。 But that rule is silly.但这条规则很愚蠢。 If you're concerned about this, then you should create a one dimensional array in the first place.如果您对此感到担忧,那么您应该首先创建一个一维数组。

The problem you are having here is that the size of an array must be defined at compile time.您在这里遇到的问题是数组的大小必须在编译时定义。

In your case, you have multiple options:在您的情况下,您有多种选择:

  • make i a constexpr like constexpr int i = 5;使iconstexpr constexpr int i = 5;
  • use a int ** instead:使用int **代替:

     int i = 5; int tab1[i][i]; //cast to void pointer void *p = (void *)tab1; // cast to int ** auto tab1_p = (int **)p; // use it like it was an array tab1_p[1][3] = 5;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM