1

我有一个数组:

char array[4][4][2];

我想要的是一个 4x4 的表,它在每个位置分配一个由两个字符组成的字符串。但是,当我像这样初始化数组时:

char array[4][4][2] = {{"AA", "BB","  ", "  "}, {"CC", "DD", "  ", "  "}, {"EE","FF","  ","  "}};

和做:

printf("%s\n", array[0][0]);

输出是:

AABB    CCDD    EEFF 

那么,这样做的正确顺序是什么?我在任何地方都没有找到它。

4

3 回答 3

3

事实上,它是char数组的正确初始化。但您不能使用%s,因为您的数组不是 NUL ( \0) 终止的。根据您的声明,您可以写:

printf("%c%c\n", array[0][0][0], array[0][0][1]);

或者更正数组维度,使其容纳长度为 2 的字符串,后跟'\0'终止符:

char array[4][4][3] = { {"AA", "BB", "  ", "  "}, 
/*               ^  */  {"CC", "DD", "  ", "  "}, 
                        {"EE", "FF", "  ", "  "}
                      };
于 2013-10-15T14:31:54.523 回答
2

C 中的字符串需要一个终止符,'\0'. 因此,对于具有两个可见字符的字符串来说,2 字符数组太小了。

这是 C 的字符串数组初始化的一个特性,即您在执行操作时不会收到警告或错误;在 C 语言中,它经常假设您知道自己在做什么。

如果你这样做:

char foo[] = "foo";

你会得到一个自动附加终止符的四字符数组,但如果你这样做

char bar[3] = "bar";

你不会得到一个终结器,因为它不适合,但你也不会得到一个错误。

要修复它,请增加第三个大小[3]以为终结器腾出空间。

许多程序员可能会将其实现为字符指针的 2D 数组,但这比您的设计使用更多的内存。它确实为您带来了简单性:

const char *array[2][2] = { { "AA", "BB" }, { "CC", "DD" } };

这将使编译器将添加了终止符的实际字符数据放在内存中的某个array位置,并且只是一个 2x2 指针数组,指向每个字符串开头的正确位置。

于 2013-10-15T14:28:54.207 回答
2

尝试以下操作:

int ii, jj;
const char *array[2][2] = {{"hello", "world"},{"these are", "strings"}};
for (ii=0; ii<2; ii++) {
  for (jj=0; jj<2; jj++) {
    printf("%s\n", array[ii][jj]);
  }
}

这向您展示了如何正确分配字符串的二维数组 - 您无法确定每个字符串的大小,它由初始化决定。编译器将确保它们是空终止的并且一切都 - 而且它们甚至不需要都是相同的大小。

注意 - 我实际上所做的是创建一个 2D 指针数组,而不是 3D 字符数组。这更灵活,更适合您的情况,因为您似乎对字符串感兴趣(它们是字符数组,但通过指向它们的开始来引用;正如@unwind 指出的那样,它们需要以空值终止) .

于 2013-10-15T14:35:35.630 回答