Stu*_*art 2 c runtime-error scanf c-strings multidimensional-array
我正在阅读一本教科书,使用 Code::Blocks v20.03 IDE 自学 C 编程。
我真的被一个小程序迷惑了,该程序将三个小字符串读入一个二维字符数组,然后将它们打印到屏幕上。该程序的代码如下所示。
#include <stdio.h>
int main(void)
{
char *colors[3][10] = {'\0'};
printf("\nEnter 3 colors seperated by spaces: ");
scanf("%s %s %s", colors[0][0], colors[1][0], colors[2][0]);
printf("\nYour entered: ");
printf("%s %s %s\n", colors[0][0], colors[1][0], colors[2][0]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译时错误或警告为零,执行时会产生以下输出。
您输入:(空)(空)(空)
使用 IDE 的 Watches 窗口显示没有任何内容写入数组。我知道数组名称被视为指向数组中第一个元素的指针。我还了解使用下标/索引来访问数组维度内的元素(例如整数数组),因此需要将这个 char 数组中的数组第二维保持为零。
可悲的是,这让我完全困惑,所以我需要帮助来填补我的理解空白。
此致,
斯图尔特
scanf与说明符一起使用时%s,必须提供一个指向要scanf写入的内存地址的指针。因此,您必须首先创建一个内存缓冲区,该缓冲区有足够的空间来存储整个字符串。最简单的方法是声明一个类型为 的数组char。
然而,该行
char *colors[3][10] = {'\0'};
Run Code Online (Sandbox Code Playgroud)
不会声明类型为 的数组char。相反,它将创建一个多维指针数组。
如果你想创建一个类型为 的数组char,你可以这样做:
char color[10];
Run Code Online (Sandbox Code Playgroud)
如果要创建 类型的数组的数组char,可以这样做:
char colors[3][10];
Run Code Online (Sandbox Code Playgroud)
现在您可以使用该行
scanf( "%s %s %s", colors[0], colors[1], colors[2] );
Run Code Online (Sandbox Code Playgroud)
这相当于
scanf( "%s %s %s", &colors[0][0], &colors[1][0], &colors[2][0] );
Run Code Online (Sandbox Code Playgroud)
由于数组到指针的衰减。在大多数情况下,如果在表达式中使用数组的名称,它将衰减为指向数组第一个元素的指针。
请注意,使用%s是危险的,因为如果用户键入的数据超出了内存缓冲区的容纳范围(在本例中超过 9 个字符),那么就会出现缓冲区溢出,从而导致未定义的行为。
因此,这样写会更安全:
scanf( "%9s %9s %9s", colors[0], colors[1], colors[2] );
Run Code Online (Sandbox Code Playgroud)
这将匹配的字符数限制为9每个字符串的字符数,因此scanf永远不会将超过的10字符(9字符加上终止空字符)写入内存缓冲区。