您发布的代码不会编译。你确定你是从书里抄来的吗?
如果我们添加明显缺失的逗号,我们最终会得到等价的
char* words[1][40] =
{
"Goat"
"A herbivore",
"Dog"
"An omnivore",
"Fox"
"A carnivore",
"Bear"
"An omnivore",
"",
"",
NULL,
// this last line repeated 30 times...
};
我怀疑这也是我们的意图。(它会生成一个以 30 个空值终止的列表,而不仅仅是 2 个。)
我怀疑这意味着什么也没有*
:
char words[][2][40] =
{
"Goat", "A herbivore",
"Dog", "An omnivore",
"Fox", "A carnivore",
"Bear", "An omnivore",
"", ""
};
这导致数组 [10] 的数组 [40] 为char
。当然,最好清楚地表明这一点:
char words[][2][40] =
{
{ "Goat", "A herbivore" },
{ "Dog" , "An omnivore" },
{ "Fox" , "A carnivore" },
{ "Bear", "An omnivore" },
{ "" , "" },
};
关于“null”的含义仍然存在问题。如果它是一个空指针,那么在这个版本中没有(也不可能有)任何指针,因为没有指针。如果是空字符 ( '\0'
),则有 10 个,每个字符串一个。如果它是一个空字符串,那么作者使用了一个最不寻常和最令人困惑的术语;如果他的意思是空字符串,他应该说空字符串。
作为两个需要的东西:我想目的是使用哨兵。写这个(在 C 或 C++ 中)的常用方法
是使用指针,并编写如下内容:
char const* const words[][2] =
{
{ "Goat", "A herbivore" },
{ "Dog" , "An omnivore" },
{ "Fox" , "A carnivore" },
{ "Bear", "An omnivore" },
{ NULL , NULL }
};
在这种情况下,我可能会使用两个空值,但初始化数组的最后一行可以是{}
、{ NULL }
或{ NULL, NULL
}
; 它们都会对编译器产生相同的结果。
即使是非指针版本,一个空字符串就足够了。编译器也会用空字符串填充所有附加值。
最后,关于为什么需要空指针或空字符串:在 C 中,它们经常被用作哨兵:你会循环直到遇到一个:
for ( char const* const (*p)[2] = words; (*p)[0] != NULL; ++ p ) {
std::cout << (*p)[0] << " - " << (*p)[1] << std::endl;
}
在 C++ 中,您几乎从不使用哨兵,因为您可以编写如下内容:
for ( char const* const (*p)[2] = begin( words );
p != end( words );
++ p ) {
std::cout << (*p)[0] << " - " << (*p)[1] << std::endl;
}
在 C++11 中,这将是std::begin
and std::end
,但当然,在 C++11 之前,每个人在他们的个人工具包中都有它们的实现。在 C++11 中,您还可以使用auto
:
for ( auto p = begin( words ); p != end( words ); ++ p ) {
std::cout << (*p)[0] << " - " << (*p)[1] << std::endl;
}
但是,我不确定这是否能给我们带来很多好处。使用的时候还是要注意复杂的类型。(auto
当您拥有基本上易于使用但难以拼写的类型时,确实会购买很多,例如迭代器。)
最后,当然,无论是在 C 中还是在 C++ 中,都不会有人为此使用二维数组。我们将定义一个结构:
struct Mapping
{
char const* animalName;
char const* eatingType;
};
Mapping const map[] =
{
{ "Goat", "A herbivore" },
{ "Dog" , "An omnivore" },
{ "Fox" , "A carnivore" },
{ "Bear", "An omnivore" },
{ NULL , NULL }
};
for ( Mapping const* p = map; p->animalName != NULL; ++ p ) {
// ...
}
(当然,在 C++ 中使用begin
andend
而不是哨兵。)
顺便说一句:除非你严重错误地引用了这本书,否则就把它扔掉。作者显然既不懂 C 也不懂 C++。