为什么这个C代码打印一个字符串从一个2D数组与下一个?



下面的代码用于打印2D数组中的字符串元素。由于所有字符串的最大长度为5,因此我将其初始化为max元素长度为5。

#include <stdio.h>
#include <string.h>
int main()
{
char arr[4][5] = {"abcde", "efghi", "ijklm", "nop"};
for(int i = 0; i < 4; i++){
printf("String: "%s" with length: %dn", arr[i], (int) strlen(arr[i]));
}
return 0;
}

但是结果是

字符串:"abcdeefghiijklmnop">
font - family:宋体;
font - family:宋体;
font - family:宋体;长度:3

,这不是我想要的结果,因为我希望它们分开打印。

现在,我将数组arr可以存储的字符串的最大大小更改为6。

#include <stdio.h>
#include <string.h>
int main()
{
char arr[4][6] = {"abcde", "efghi", "ijklm", "nop"};
for(int i = 0; i < 4; i++){
printf("String: "%s" with length: %dn", arr[i], (int) strlen(arr[i]));
}
return 0;
}

但是现在的结果是:

字符串:"abcde">
font - family:宋体;
font - family:宋体;
font - family:宋体;长度:3

这是否与指针有关?因为我认为二维数组中包含了物理上以连续方式存储的指针。

C中的字符串实际上是char对象的数组。此外,每个有效字符串必须以值为0的字符结束。这个额外的0字节标志着字符串的结束。终止符被隐式地添加到任何字符串字面值。这就是为什么"abcde"由6个char-s组成。

在你的声明:

char arr[4][5] = { "abcde", ... };

字符串"abcde"对于数组的第二维char[5]来说太。终止符被忽略。结果"abcde"与后面的字符串合并,因为它们之间没有终止符。

现在printf("%s", arr[0])打印字符直到找到0字节。这就是为什么你看到abcdeefghiijklmnop。所有字符串被合并。

健壮的修复不是使用char的2D数组,而是使用指向常量字符串的指针数组。数组中的每一项都是字符串实际所在的地址。

const char *arr[4] = {"abcde", "efghi", "ijklm", "nop"};
for(int i = 0; i < 4; i++)
printf("String: "%s" with length: %dn", arr[i], (int) strlen(arr[i]));