我已经在C中声明了一个大小为1的字符数组,但是我已经读取了一个大小为10的字符串,但是给出的代码工作得非常好。 #包括 int main() { 字符名[1]; scanf(“%s”,名称); printf(“%s”,名称); }
我可以通过此声明读取任意大小的字符串首先,这是未定义的行为。这种情况下会发生什么是不可预测的 然而,我将给出一个额外的代码示例,其中包含一个额外的变量,以说明这种方法可能出现的错误我已经在C中声明了一个大小为1的字符数组,但是我已经读取了一个大小为10的字符串,但是给出的代码工作得非常好。 #包括 int main() { 字符名[1]; scanf(“%s”,名称); printf(“%s”,名称); },c,string,C,String,我可以通过此声明读取任意大小的字符串首先,这是未定义的行为。这种情况下会发生什么是不可预测的 然而,我将给出一个额外的代码示例,其中包含一个额外的变量,以说明这种方法可能出现的错误 #include<stdio.h> int main() { char name[1]; scanf("%s",name); printf("%s",name); } 这是您的原始程序,带有一个附加变量,a,它被初始化为1且未更改 输出 int main() { char
#include<stdio.h>
int main()
{
char name[1];
scanf("%s",name);
printf("%s",name);
}
这是您的原始程序,带有一个附加变量,a
,它被初始化为1且未更改
输出
int main()
{
char name[1];
int a=1;
printf ("a = %d\n",a);
scanf("%s",name);
printf("%s\n",name);
printf ("a = %d\n",a);
}
正如您所看到的,
a
的值通过输入一个大字符串而改变。首先,这是未定义的行为。这种情况下会发生什么是不可预测的
然而,我将给出一个额外的代码示例,其中包含一个额外的变量,以说明这种方法可能出现的错误
#include<stdio.h>
int main()
{
char name[1];
scanf("%s",name);
printf("%s",name);
}
这是您的原始程序,带有一个附加变量,a
,它被初始化为1且未更改
输出
int main()
{
char name[1];
int a=1;
printf ("a = %d\n",a);
scanf("%s",name);
printf("%s\n",name);
printf ("a = %d\n",a);
}
正如您所看到的,
a
的值是通过输入一个大字符串而改变的。对于C的新手,我想解释一下实际发生的情况:
在C语言中,数组是一个连续的内存块,由指向该数组的第一个单元(内存块的第一个字节)的指针表示
下面是如何查找带有一个单元格的字符数组:
a = 1
aaaa
aaaa
a = 6381921
您在某处分配了一个字节的内存,变量name
保存该字节的地址。
它不包含数组的长度,该信息仅用于分配它,然后被丢弃
当您调用scanf
时,它会获取name
中的地址,并开始用用户输入填充内存。由于scanf
没有关于尺寸的信息,因此只有在两种情况下才会停止:
1.输入结束
2.写入内存时出错
这就是为什么不可能知道会发生什么,因为这在很大程度上取决于正在运行的程序的内存布局,而内存布局又取决于硬件、操作系统和编译器
它还取决于输入的长度
在这个简化的示例中,scanf
将继续写入地址8、9及以上。
假设您的程序可以写入这些地址,它将用用户输入替换其中的任何内容
printf
将从7开始读取内存(名称中的地址),直到它进入一个值为0的字节,并将所有内容打印到屏幕上
如果在调用scanf
和调用printf
之间没有其他代码使用该内存,则输入数据仍将存在,并将正确打印到屏幕上
但是,如果有使用这些内存地址的代码,它可能会覆盖输入或破坏程序,因为它从内存中读取了错误的数据。对于C新手,我想解释一下实际发生的情况: 在C语言中,数组是一个连续的内存块,由指向该数组的第一个单元(内存块的第一个字节)的指针表示 下面是如何查找带有一个单元格的字符数组:
a = 1
aaaa
aaaa
a = 6381921
您在某处分配了一个字节的内存,变量name
保存该字节的地址。
它不包含数组的长度,该信息仅用于分配它,然后被丢弃
当您调用scanf
时,它会获取name
中的地址,并开始用用户输入填充内存。由于scanf
没有关于尺寸的信息,因此只有在两种情况下才会停止:
1.输入结束
2.写入内存时出错
这就是为什么不可能知道会发生什么,因为这在很大程度上取决于正在运行的程序的内存布局,而内存布局又取决于硬件、操作系统和编译器
它还取决于输入的长度
在这个简化的示例中,scanf
将继续写入地址8、9及以上。
假设您的程序可以写入这些地址,它将用用户输入替换其中的任何内容
printf
将从7开始读取内存(名称中的地址),直到它进入一个值为0的字节,并将所有内容打印到屏幕上
如果在调用scanf
和调用printf
之间没有其他代码使用该内存,则输入数据仍将存在,并将正确打印到屏幕上
但是,如果有使用这些内存地址的代码,它可能会覆盖输入或破坏程序,因为它从内存中读取了错误的数据。未定义的行为。它可能有效,也可能无效。您是否建议所有数组的长度都应为1,因为在这种情况下没有发生任何不好的事情?你完全错了,程序将使用“任意长度的字符串”。不要忘记,
scanf
将在第一个空格处停止,因此您的字符串可能只有几个字节的长度。实际上,它并不正常:只是您看不到出错的影响。如果使用Valgrind或GDB运行它,您会看到一些错误(内存错误)。如果你要进一步处理name
,你很可能会遇到SEGFULT。“我去了一个繁忙的十字路口。红灯亮了。我还是过了马路。过得很好。”这是否意味着冲红灯过十字路口是可以的?未定义的行为。它可能有效,也可能无效。您是否建议所有数组的长度都应为1,因为在这种情况下没有发生任何不好的事情?你完全错了,程序将使用“任意长度的字符串”。不要忘记,scanf
将在第一个空格处停止,因此您的字符串可能只有几个字节的长度。实际上,它不起作用:只是您看不到