是否可以将char [] []传递给请求char **的函数?

时间:2011-12-04 02:34:23

标签: c++ c arrays pointers char

我正在尝试调用一个以char **作为参数的函数。它的工作是填充一个字符串数组(即char *数组)。我知道字符串的最大长度,并且我可以传递最大数字作为另一个参数填充,所以我希望堆栈像这样分配:

fill_my_strings(char** arr_str, int max_str); // function prototype

char fill_these[max_strings][max_chars_per_string]; // allocating chars
fill_my_strings(fill_these, max_strings); // please fill them!

当然,我得到“无法将char [max_strings] [max_chars_per_string]转换为char **”错误。

我知道这是一个微妙的(或不那么微妙的)问题,我理解了数组和指针之间的区别。我只是不确定为什么不可能将这块内存传递给想要char **的东西并让它填充我的堆栈分配的字符。有人可以解释一下这是否可能,或者如果没有,为什么不呢?

是否可以在不调用malloc / new的情况下调用此类函数?

4 个答案:

答案 0 :(得分:3)

你问题的简单答案是否定的;二维数组与指针指针类型不同。数组衰减指向其第一个元素的指针,但实际的指针该值。

如果您将两者都转换为char*

,这些类型之间的区别很明显
int x;
char *arr_pp[] = {"foo", "bar", "baz"};
char arr_2d[][4] = {"foo", "bar", "baz"};

char *cp = (char*)arr_pp;
for(x=0; x<3; x++)
     printf("%d ", cp[x]);
printf("\n");

cp = (char*)arr_2d;  
for(x=0; x<3; x++)
     printf("%d ", cp[x]);
printf("\n");

输出(在我的电脑上)是:

-80 -123 4 
102 111 111 

第一行是由于我正在打印一个转换为字节的地址而形成的乱码,而第二行是ascii值为“foo”。

在一个带char **的函数中,编译器无法知道衰减数组类型,它们实际上并不包含指针。

答案 1 :(得分:2)

我不确定为什么fill_my_strings()需要char**参数。从您的示例中,调用者已经从堆栈中分配了内存。所以使用char*应该没问题。

但是,如果您想使用char**或无法修改fill_my_strings()功能,请尝试以下示例代码:

void fill_my_strings(char** arr_str, int max_chars_per_string, int max_strings)
{

    for(int i = 0; i < max_strings; ++i)
    {
        //Make sure you have enough space
        memcpy(*arr_str, "ABCD", sizeof("ABCD"));

        *arr_str += max_chars_per_string;
    }
}

char fill_these[max_strings][max_chars_per_string];
char* pointer = (char*)fill_these;
fill_my_strings(&pointer, max_strings, max_chars_per_string);

答案 2 :(得分:2)

假设你有n个指针指向m-1个最大字符的字符串(m个字符包括NULL)。 所以,在纯C: sizeof(char [n] [m])将返回n * m。 sizeof(char **)将返回架构中指针的大小,可能是32(如果是x86)或64(如果是x86_64)。

char [n] [m]实际上是连续分配n * m字节。 char **分配一个指针。该指针引用* n字节的内存条带。这些n个指针中的每一个都指向一个m个字符的内存条带。

所以,考虑到sizeof(char)== u,如果你声明char a [n] [m],当你使用[i] [j]时,编译器会理解*(a + i * m * u + j * u)。 所以,考虑到sizeof(char *)== w,如果你声明char ** a,当你使用[i] [j]时,编译器会理解(a + i * w) + j * w)。

完全不同的数据管理。

你可以做的关闭事情就是创建一个char **变量,并用堆栈分配矩阵的地址填充它。

char **tmp = malloc(max_strings * sizeof(char *));
int i;
for(i = 0; i < max_strings; i++){
    tmp[i] = &(fill_these[i][0]); //you probably can't reference a char[][] with a single index - not confirmed
}

答案 3 :(得分:0)

显而易见的事情是建立一个索引

在c中使用类似:

char string_list[num_strings][str_length];

// ...

char**index = calloc( (num_strings+1), sizeof(*index) ); // calloc insures NULL termination
for (int i=0; i<num_strings; ++i) {
   index[i] = string_list[i]
}

在c ++中,首选new[]calloc;