C ++ char * []到char **的转换

时间:2013-12-09 09:42:57

标签: c++ type-conversion

我有这个简单的代码,编译时没有错误/警告:

void f(int&, char**&){}

int main(int argc, char* argv[])
{
    f(argc, argv);
    return 0;
}

下一个不编译的类似代码:

void f(int&, char**&){}

int main()
{
    int argc = 2;
    char* argv[] = { "", "", nullptr };
    f(argc, argv); 
    //@VS2013 error: cannot convert argument 2 from 'char *[3]' to 'char **&'
    //@GCC error: invalid initialization of non-const reference of type 'char**&' from an rvalue of type 'char**'
    return 0;
}

为什么char*[]可以在第一个样本中转换为char**&而在第二个样本中无法转换?如果在编译时知道大小是否重要?

编辑:我认为在第二种情况下需要进行2次转换,编译器只能进行一次隐式转换。

此代码编译良好:

void f(int&, char**&){}

int main()
{
    int argc = 2;
    char* temp[] = { "", "", nullptr };
    char** argv = temp;
    f(argc, argv);
    return 0;
}

3 个答案:

答案 0 :(得分:9)

因为尽管出现了main的第二个参数 输入char**。用作函数的声明时 参数,顶级数组被重写为指针,因此char *[]实际上是char**。这仅适用于功能 然而,参数。

char*[](如第二种情况)可以转换为char**, 但是转换的结果(与任何转换一样)是一个 rvalue,不能用于初始化非const引用。 你为什么要参考?如果是修改指针, 将char**参数修改为main是未定义的行为 (正式地,在C中,至少 - 我没有检查过C ++是否更多 自由派在这里)。当然,你没办法 修改数组的常量地址。如果你不想要的话 要修改它,为什么要使用引用?

答案 1 :(得分:3)

Jefffrey's comment引用标准,现在是:

  

4.2数组到指针的转换[conv.array]

     

可以转换“N T数组”或“T未知数组”的左值或右值   到“指向T的指针”的prvalue。结果是指向的指针   数组的第一个元素。

prvalue是:

  

prvalue(“纯”rvalue)是一个标识临时值的表达式   对象(或其子对象)或者是与any无关的值   对象

您不能将非const引用绑定到临时引用。

int& i = int(); // error

char* argv[] = { "", "", nullptr };
// the result of the conversion is a prvalue
char**& test = argv; // error

因此,以下代码将很乐意编译:

#include <iostream>

void f(int& argc, char** const& argv){
    std::cout << argv[0] << std::endl; // a
}

int main()
{
    int argc = 2;
    char* argv[] = { "a", "b", nullptr };
    f(argc, argv); 
    return 0;
}

我在Kanze's comment中指出了一件重要的事情。

在OP中提供的第一个示例中,char* argv[]char** argv是等效的。因此,没有转换。

std::cout << std::is_array<decltype(argv)>::value << std::endl; // false
std::cout << std::is_array<char**>::value << std::endl; // false
std::cout << std::is_array<char*[]>::value << std::endl; // true
std::cout << std::is_same<decltype(argv), char**>::value << std::endl; // true
std::cout << std::is_same<decltype(argv), char*[]>::value << std::endl; // false

答案 2 :(得分:0)

temp的类型
  

char* temp[] = { "", "", nullptr };

char * [],它是

  

char*[3]

后者不能隐式转换为`char **'。

main中,argv的类型是未绑定的char*数组,相当于char**

我承认,这令人困惑:)