无法从'T [N] [2]'转换为'T [] [2]'

时间:2011-01-13 09:42:41

标签: c++

我有一个API有一些选择:

void init_api(const char* options[][2]);

我被允许传递一个没有选项的NULL指针,或者,可以传递像这样的选项数组:

const char* some_options[][2] = { {"opt1", "val1"}, 
                                  {"opt2", "val2"}, 
                                  {0,0} 
                                };

可以正常运行:

...
init_api(some_options);
... or ...
init_api(NULL);
...

然而,无法编译

const char* my_options[][2] = NULL; // error C2440: 'initializing' : cannot convert from 'int' to 'const char *[][2]'
if(...) {
  my_options = some_options; // error C2440: '=' : cannot convert from 'const char *[4][2]' to 'const char *[][2]'
}
init_api(my_options); // no error here

这里发生了什么?有人可以解释一下吗?

4 个答案:

答案 0 :(得分:3)

要声明一个指向const char的指针数组的空数组,您应该使用:

const char* my_options[][2] = {};

您需要声明一个指向const char指针数组的指针。我建议使用typedef来简化语法。

typedef const char* array_of_two_cstring[2];
array_of_two_cstring* my_options = NULL;
if (...) {
    my_options = some_options;
}
init_api(my_options);

在C ++中(它是从C中删除),数组可以隐式转换为指针(只有一次,char[]char*兼容但char[][]与{ {1}}但不是`char **)。但是,无法重新分配变量。所以在这里你需要使用指针而不是数组。

char*[]选项接受init_api作为参数,因为对于编译器,其原型是NULL(第一个数组退化为指针),而void init_api(char const* (*)[2])是一个有效指针。

答案 1 :(得分:3)

编译器必须知道数组大小。

如果省略数组的大小(即:使用[]),则需要使用定义初始化数组,以便让编译器计算数组将包含的项目数。

此外,您正在为数组指定一个指针(NULL):const char *x[][2]是一个包含两个指针const char的数组。


修改

在C ++中(如在C中),当你使用它们时,数组可以衰减为指针(有三个例外,这里不感兴趣)。

当你将一个数组传递给一个期望一个数组的函数时,你会发生一个指向数组的指针,因为数组会衰减;你不能在C或C ++中按值传递数组。

因此,您可以将NULL传递给您的函数;函数参数将为NULL,如果您尝试访问函数中的数组(options[0]),您的应用程序将崩溃:您将取消引用无效指针。

但是你不能将你的数组变量设置为NULL,因为它不是指针,它是一个数组:它只会在你在表达式中使用它时才会衰减。

答案 2 :(得分:1)

const char* options[][2]  

是一个const char *指针数组。您无法指定指向数组的指针。

答案 3 :(得分:1)

声明为类型为T[N]T[]的数组的参数实际上变为类型T*的参数。对函数也是如此(声明为R(Params)的参数实际上变为类型R(*)(Params...)的参数)。

然而,这种转换不适用于其他声明。为函数按值参数完成的原因是C中没有办法直接实际复制数组(即实际复制其内容),尝试复制函数也没有意义,所以这些参数以一种以有意义的方式传达其目的的方式进行转换。

因此,当你在函数参数的情况下初始化一个指针时,你试图在另一种情况下初始化一个数组。