char**与char* c[]用于访问字符串数组的区别

9
为什么我不能将char**指向C字符串数组?
int main(int argc, char *argv[]) {

    char* c1[] = {"Hey","Hello"};
    printf("%s",c1[1]);

} //works fine

vs

int main(int argc, char *argv[]) {

    char** c1 = {"Hey","Hello"};
    printf("%s",c1[1]);

} //error

6
指针不是数组。 - R. Martinho Fernandes
5个回答

11

我认为这里的混淆源于认为{"Hey","Hello"}是一个数组,但它不是。它根本不是一个对象,而只是一种特殊的初始化语法,可用于初始化数组。你无法使用它来初始化char**,因为char**是一个指针,而不是数组。它不会自动创建一个数组对象,可以转换为指针。

也许你在想它像Python中的[...]列表或JavaScript中的{ ... }对象。它根本不像那些东西。那些表达式实际上会创建该类型的对象,并且可以在任何可以接受这些对象的表达式中使用。我们在C++中使用的语法仅仅是一种初始化语法。

例如,你可以这样做:

const char* array[] = {"Hey","Hello"};
const char** p = array;

然而,您不能做像这样的傻事:

std::cout << {"Hey", "Hello"}[1];

在这里,我们实际上创建了一个数组对象,其中将存储指针。只有在这之后,我们才能将该数组转换为const char **


4

将其更改为

char** c1 = (char *[]){"嗨","你好"};


这个答案似乎最接近问题的本质。 - Danijel

1
int main(int argc, char *argv[]) {

    char** c1 = {"Hey","Hello"};
    printf("%s",c1[1]);

} //error

在上面的代码中,您试图将指针设置为指向包含“Hey”和“Hello”地址的两个指针的集合。这两个指针的存储位置在哪里?不存在。
您可以进行以下操作:
 char *a = "Hey";
 char *b = "Hello";
 char *c[] = { a, b };     // This MAY not compile due to a and b not being compile time constants. 
 char **c1 = c;

我已经将它分成了更多的变量,比它实际需要的还要多,但我认为这解释了你的代码有什么“问题”。
另一个例子是,如果我们将char *改为int:
 const int a = 1;
 const int b = 2;

 int c[] = { a, b };

 int *c = { a, b };   // Doesn't work, there is nowhere to store a copy of a and b. 

这是相同的事情,只是使用整数。


1
为什么我不能将char **指向C字符串数组?
正如您所说,c1是一个数组。因此,您必须将其声明为char指针的数组。
由于"Hey""Hello"是字符串字面量,每个c1[i]字符串都指向一个匿名字符串。这就是为什么可以使用指向char的指针而不是char数组的原因。
但是,要创建指向char的指针数组,您不能使用char **

0
"

\"char **c1\"告诉编译器它是一个指向char类型的指针,是标量类型(一个值)。

仅使用值列表进行初始化仅适用于聚合类型。

"

char **c1 没有歧义。它是一个指向 char 指针的指针。(当然,上面的两个指针都可以指向数组的第一个元素。) - James Kanze
@James Kanze,是的,我的错。已删除。 - Arun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接