为什么scanf中需要%hd?

我创建了一个非常简单的程序,其中包含一个值,然后将其记忆到局部变量值,最后使用第二个选项,程序打印该值。

我的问题是:为什么只有在scanf参数中添加“h”时程序才能工作? 换句话说:scanf()和我的本地int值变量之间有什么样的关系?

谢谢!

pS(我用Dev-C ++(GCC)编译它。用Visual Studio工作)

#include  main () { int value = 0; short choice = 0; do { printf("\nYour Choice ---> "); scanf("%d", &choice); /* replace with "%hd" and it works */ switch (choice) { case 1: printf("\nEnter a volue to store "); scanf("%d", &value); getchar(); printf("\nValue: %d", value); break; case 2: printf("\nValue: %d", value); break; } } while (choice < 3); getchar(); } 

使用scanf ,“h”修饰符表示它正在读取一个短整数,这是您的变量choice恰好。 所以“%hd”只需要写两个字节(在大多数机器上)而不是“%d”写入的4个字节。

有关详细信息,请参阅scanf上的此参考页面

变量choice类型为short ,这就是为什么你需要scanf中的%h说明符读入它(实际上你不需要这里的d )。 int类型只需要%d 。 请在此处查看有关转化的说明

你正在读短片。 h是必要的,因为默认情况下%d是int的大小。 请参阅scanf上的此参考页面 。

看起来你的问题是choice是一个short ,通常是2个字节长,而%d期望一个整数,通常是4个字节长…所以scanf破坏了堆栈上choice后的任何东西。

choiceshort ,%d指定int

当您指定%d时,scanf必须假定关联的参数是指向int大小的内存块的指针,并将为其写入一个int 。 当发生这种情况时,它可能会写入相邻但不是choice一部分的数据,结果是不确定的,可能不是很好! 如果它在一个编译器中工作而不是另一个编译器只是未定义行为的本质!

在GCC -Wformat中,当你犯这个错误时应该给你一个警告。

来自comp.lang.c FAQ:

  • 为什么代码没有short int s; scanf("%d", &s); short int s; scanf("%d", &s); 工作?
  • 有人告诉我,将%lfprintf一起使用是错误的。 如果scanf需要%lfprintf如何使用%f作为double类型?

%d用于读取int ,而不是short。 你的代码从未真正“起作用” – 只是看起来在这种情况下你没有注意到你想要的和你所获得的未定义行为之间的任何差异。

scanf用于输入short类型变量的修饰符是%hd。 因此,您需要指定正确的修饰符。

 scanf("%d",&integer); // For integer type scanf("%hd",&short_int); // For short type 

因此它不起作用。

根据数字填充,字节序和其他此类问题,您可能将输入值的上部或下部存储到选项中; 您将其余的输入值存储到可能用于或不用于其他任何内容的内存中。