将char[][]转换为char**

Convert char[][] to char**

本文关键字:char 转换      更新时间:2023-10-16

我有一个char[][]

  char c[2][2]={
    {'a','b'},
    {'c','d'}
  };

如何将其转换为char** ?

这里的目标是使用转换后的char**作为main函数的输入,该函数只接受char**作为其输入。

虽然您可以轻松地从char[]切换到char*,但对于char[][]char**则不可能:

  • 你的char[2][2]是一个二维数组,所有元素都连续存储。为了访问一个元素,编译器在知道每行大小的情况下计算偏移量。
  • char**指向一个数组,该数组包含指向char的指针。要访问一个元素,编译器计算最左边指针的偏移量,加载该指针,然后访问该元素。

处理:

char *pc[2]={c[0],c[1]}; 
cout << pc[1][1]<<endl;   // prints out the same as c[1][1]
// you can pass `pc` when a `char**` is needed

备注: 这可以完美编译。然而,一些带有char **av之类参数的函数实际上希望av[i]是一个以空结束的c-string。在这种情况下,尽管您的代码可以编译,但结果可能不是您所期望的(缓冲区溢出)。

不能将char[2][2]转换为char**,只能将其转换为char(*)[2]

char (*p)[2] = c;

上面是一个指向2字符数组的指针。请注意,您需要这个2,而不能只写char** p,因为在后一种情况下,您无法执行指针算术(指针在递增时不知道要"跳转"多少元素,并且您将无法寻址数组的元素(在本例中为行))。

您可以像这样将数组传递给函数:

char c[2][2] = {
    {'a','b'},
    {'c','d'}
};
char* x[] { c[0], c[1] };
func(x); // Assuming something like: void func(char** p);

注意:虽然这个答案可以很好地解释/说明问题,但建议创建一个自动变量 char*[2];,而不是像这个答案那样使用new分配。

原始答:

问题是char c[2][2]char的一个连续块。编译器只分配4个char对象。

当你构建数组 (char** c)的数组时,你需要手动分配一个指针数组char,然后分配(或分配)一个char数组给每个指针。

因此,要数组char c[2][2]转换为数组的数组,必须首先创建指针数组,然后将每个 char数组的第一个元素的数组赋值给它。

像这样:

void func(char** c)
{
    for(int x = 0; x < 2; ++x)
        for(int y = 0; y < 2; ++y)
            std::cout << c[x][y] << ' ';
    std::cout << 'n';
}
int main(int, char* argv[])
{
    // one contiguous block of 4 chars
    char c[2][2]={
        {'a','b'},
        {'c','d'}
      };
    char** param = new char*[2]; // create your own pointer array
    param[0] = &c[0][0]; // assign the first element of each char array
    param[1] = &c[1][0];
    func(param); // call your func
    delete[] param; // cleanup
}

如果你有C++11,你可以使用智能指针来防止内存泄漏,如果抛出异常或有人忘记delete

int main(int, char* argv[])
{
    // one contiguous block of 4 chars
    char c[2][2]={
        {'a','b'},
        {'c','d'}
      };
    // use a smart pointer
    std::unique_ptr<char*[]> param(new char*[2]);
    param[0] = &c[0][0];
    param[1] = &c[1][0];
    func(param.get()); // now if this throws, no memory leak
    // delete[] param; // NO NEED TO DELETE
}