以下代码的输出是什么?
#include <stdio.h>
int n;
int main() {
scanf("&d", &n);
switch (n) {
case 1:
printf("hello\n");
break;
case 2:
printf("good\n");
break;
default:
printf("Morning\n");
break;
}
return 0;
}
大多数人都希望有一个错误,但在执行时,无论给出什么输入,它总是输出Morning
。
输出将始终是Morning
。
scanf("&d")
希望输入两个字符&
和d
,字面意思。如果您输入任何其他内容,scanf
调用将失败。但是,您的代码不会检查scanf
的返回值,因此没有区别。
&n
的scanf
参数被忽略,因为格式字符串中没有“转换规范”(那些以%
开头的东西)。因此(如C标准所述(C99,7.19.6.2 fscanf
函数/ 2)):
如果参数保留时格式已用尽,则会评估多余的参数(一如既往),否则将被忽略。
因此,scanf("&d", &n)
仅相当于scanf("&d")
。
当switch (n)
检查n
时,它仍将包含初始化的值。没有显式初始值设定项,因此它设置为0
(因为它是一个全局变量(具体来说,因为它具有静态存储;请参阅C99,6.7.8初始化/ 10))。
没有case 0:
标签,所以default:
踢。
“早晨”是此计划的正确输出。
首先,没有理由期待错误消息,因为程序不会打印任何一个。特别是,诸如scanf()
之类的C标准库函数不会向标准流发出错误消息。相反,它们通过返回值返回状态信息,在某些情况下,通过设置线程局部变量errno
。此程序甚至不检查scanf
的返回值,因此没有理由认为它会因为任何问题而发出错误消息。
其次,尽管传递给scanf
的格式字符串似乎包含拼写错误,但它仍然是一种完全有效的格式。它告诉scanf
尝试阅读(但不做任何其他的)双字符序列“&d”。如果那些不是它看到的接下来的两个字符,那么它将失败并出现匹配错误,它将通过返回0来指示。事实上,如果它们是接下来的两个字符,它也将返回0,因为返回值传达了成功扫描,转换和存储的输入字段数,格式不描述任何输入字段。
在所有情况下都忽略第二个scanf
参数,但是一些编译器会发出关于它的警告(而不是错误)。
由于scanf
没有为变量n
赋值,因此它保留了调用之前的任何值。由于它是在文件范围内声明的,因此在程序启动之前它会自动初始化为零,并且当exectution到达switch
语句时它仍然具有此值。这导致默认情况被执行。