Ampersand in PlaceHolder of scanf?

问题描述 投票:0回答:2

以下代码的输出是什么?

#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

c scanf
2个回答
5
投票

输出将始终是Morning

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

&nscanf参数被忽略,因为格式字符串中没有“转换规范”(那些以%开头的东西)。因此(如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:踢。


2
投票

“早晨”是此计划的正确输出。

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

其次,尽管传递给scanf的格式字符串似乎包含拼写错误,但它仍然是一种完全有效的格式。它告诉scanf尝试阅读(但不做任何其他的)双字符序列“&d”。如果那些不是它看到的接下来的两个字符,那么它将失败并出现匹配错误,它将通过返回0来指示。事实上,如果它们是接下来的两个字符,它也将返回0,因为返回值传达了成功扫描,转换和存储的输入字段数,格式不描述任何输入字段。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.