是否在scanf的HoldHolder中?

时间:2018-09-07 18:02:44

标签: c scanf

以下代码的输出是什么?

#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

2 个答案:

答案 0 :(得分:5)

输出将始终为Morning

scanf("&d")从字面上期望输入两个字符&d作为输入。如果您键入其他任何内容,则scanf调用将失败。但是,您的代码不会检查scanf的返回值,因此没有区别。

&n的{​​{1}}参数将被忽略,因为格式字符串中没有“转换规范”(以scanf开头的东西)。因此(如C标准所说(C99,7.19.6.2 %函数 / 2)):

  

如果在保留参数的情况下用尽了格式,则多余的   对参数进行评估(一如既往),否则将被忽略。

因此

fscanf仅相当于scanf("&d", &n)

scanf("&d")检查switch (n)时,它仍将包含初始化时使用的值。没有显式的初始化程序,因此将其设置为n(因为它是全局变量(特别是因为它具有静态存储;请参阅C99,6.7.8 Initialization / 10))。

没有0标签,因此case 0:会加入。

答案 1 :(得分:2)

“早晨”是此程序的正确输出。

首先,没有理由希望收到错误消息,因为该程序不会在任何地方打印出错误消息。特别是,诸如scanf()之类的C标准库函数不会向标准流发出错误消息。而是通过返回值返回状态信息,在某些情况下,它们通过设置线程局部变量errno返回状态信息。该程序甚至不检查scanf的返回值,因此没有理由认为由于那里的任何问题它都会发出错误消息。

第二,尽管传递给scanf的格式字符串似乎包含错字,但它仍然是完全有效的格式。它告诉scanf尝试读取(但不执行其他操作)两个字符的序列“&d”。如果这不是接下来看到的两个字符,那么它将失败并显示匹配错误,并通过返回0来指示错误。实际上,如果这两个字符是后两个,则 也将返回0。 ,因为返回值传达成功扫描,转换和存储的输入字段的数量,并且格式不描述任何输入字段。

在所有情况下,第二个scanf参数都将被忽略,但是某些编译器会发出有关它的警告(不是错误)。

由于scanf没有为变量n赋值,因此它将保留调用前的值。由于它是在文件作用域中声明的,因此在程序启动之前它会自动初始化为零,并且当执行达到switch语句时,它仍然具有该值。这将导致执行默认情况。