为什么不能使用char指针的指针而使用char指针数组?

8

当我尝试使用以下代码中的第二个选项来初始化names时,会出现分段错误。我猜测第二个选项在概念上存在问题。有什么想法吗?

 char *names[] = {
            "Alan", "Frank",
            "Mary", "John", "Lisa"
        };

 char **names = {
            "Alan", "Frank",
            "Mary", "John", "Lisa"
        };

char name[] = "Allan"; char **names = &name;char name[] = "Allan"; char **names = &name; - Agent_L
也许告诉我们你为什么如此热衷于 **。它们除了通过参数从函数返回外几乎没有用处。 - Agent_L
@Agent_L 我正在跟随《学习C语言的艰苦之路》(http://c.learncodethehardway.org/book/learn-c-the-hard-waych16.html)这本书,其中有一个练习是“将程序中所有的数组使用重写为指针”。 - stressed_geek
2
这是非常晦涩的指令。指针必须指向数组的一个元素,才能让++、--和[i]的魔法生效。我相信他的意思是通过移动指针(++)来访问所有数组,而不是通过[i]。指针只是访问数组的一种方式,而不能完全替代它们。 - Agent_L
@Agent_L 嗯,我想你是对的。一开始阅读那些晦涩的指示时我有点困惑。谢谢! - stressed_geek
4个回答

6

是的,第一种情况下,你有一个指针数组。每个指针指向一个单独的项目(Alan、Frank等)。

第二个声明:

char **names;

这意味着names是一个指向指针的指针[你不能像这样初始化一组字符串]。就像

char *str = "hello"
char **names = &str;

2

它具有完全不同的内存布局。

你的第一个例子是一个指针数组。它占据了一个 char * 的5倍大小。

然而,你的第二个例子是一个指向一个或多个char *应该出现的位置的指针。不能以你所做的方式初始化它。


谢谢,对于第二个选项初始化的正确方式是什么? - stressed_geek
2
第一种方式是正确的。char **names不是一个数组,而是一个指向指针的指针,因此可以像我之前发布的那样保存指针的地址。 - Manik Sidana
@stressed_geek 你可以使用char**(第二种方式)指向一个数组(第一种方式)。但首先,你必须初始化它。char * names[]={...}; char ** n2 = &names; 可以是一种方法... - glglgl

2
在第一种情况下,您拥有一个char*数组。这意味着,您已经为5个char*变量(数组的条目)分配了内存,它们整齐地坐在内存中紧挨着另一个。此外,它们中的每一个都初始化为每个字符串的开头。
在第二种情况下,您只有一个char**类型的指针。您只有足够一个指针的内存。
(我跳过了讨论为每个字符串分配的内存。它可能在两种情况下都相同,但在这里无关紧要)

0

使用gcc不会导致段错误。然而,尝试使用整数数组进行相同的操作可能会说明为什么这没有太多意义:

char* names[] = { "Dennis", "Richie" };
char** more_names = { "Sarah", "O'connor" };

printf("Name: %s %s\n", names[0], names[1] );
printf("Name: %s %s\n", more_names + 0, more_names + 1);

int numbers[] = { 0, 1 };
int x = 2, y = 3;
int* more_numbers = { &x, &y };

printf("Numbers: %d, %d\n", numbers[0], numbers[1] );
printf("Numbers: %d, %d\n", *(more_numbers + 0), *(more_numbers + 1));

奇怪的是,这个例子实际上对于整数数组产生了预期的结果。然而gcc确实会产生一个警告。


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