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

C++ char*[] to char** conversion

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

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

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**&,而在第二个样本中不能转换?在编译时是否知道大小有关系吗?

编辑:我认为第二种情况需要两个转换,编译器只能完成一个隐式转换。

此代码编译良好:

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

因为尽管出现了,main的第二个参数类型CCD_ 4。用作函数的声明时参数,顶级数组被重写为指针,所以char *[]实际上就是char**。这仅适用于函数然而,参数。

CCD_ 7(如第二种情况)可以转换为CCD_,但是转换的结果(与任何转换一样)是rvvalue,并且不能用于初始化非常量引用。你为什么想要推荐信?如果要修改指针,将char**参数修改为main是未定义的行为(从形式上讲,至少在C中,我没有检查C++是否更这里是自由主义者)。当然,你不可能修改数组的常量地址。如果你不想要修改它,为什么要使用引用?

Jefffrey的评论引用了标准,这里是:

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

类型为"N T的数组"或"T的未知界的数组"的左值或右值可以转换到类型为"pointer to T"的prvalue。结果是指向数组的第一个元素。

prvalue是:

prvalue("纯"右值)是一个标识临时对象(或其子对象)或是与任何对象

不能将非常数引用绑定到临时引用。

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的评论中指出了一件我忽略了的重要事情。

在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

temp的类型

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

而不是char*[],它是

char*[3]

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

main中,argv的类型是未绑定的char*阵列,其等效于char**

我承认,这很令人困惑:)