在 c 中扫描字符串很奇怪

Weird thing with scanning strings in c

我知道要扫描最多 4 个字符,您需要使用 %4s。如代码所示:

#include <stdio.h>

int main(void){
   char str0[4] = "123"; // 1 char for '[=10=]'
   char str1[5]; // +1 char for [=10=]
   printf("String str0 = '%s'\n", str0);
   printf("Enter 4 chars: ");
   scanf("%4s", str1);

   printf("You entered string '%s'\n", str1);
   printf("String str0 = '%s'\n", str0);
}

但我想知道,为什么将 scanf("%4s", str1) 更改为 scanf("%s", str1) 结果是这样的:

输入:

String str0 = '123'
Enter 4 chars: 123456789

输出:

You entered string '123456789'
String str0 = '6789'

编辑:我注意到使用 #include <string.h> 时输出仍然是 String str0 = '123'

But I wonder, why changing scanf("%4s", str1) into scanf("%s", str1) results into this: [...]

当您更改代码并从 scanf 中删除宽度限制时,您允许它在数组边界之外写入。这是 undefined behavior 的一个例子,对于那种没有预期输出的构造,编译器可以以任何它认为合适的方式处理它。

例如,如果我使用完全相同的编译器将您的代码编译成两个程序,gcc 10.2(包括 header <string.h>),优化和不优化(O3),每个程序的运行结果不同:

输入:

123456789

输出:

String str0 = '123'  // optimized
String str0 = '6789' // not optimized

如您所见https://godbolt.org/z/WfGer47P6


I noticed that when using #include <string.h> the output is still String str0 = '123'

未定义行为的另一个症状。