为什么转换说明符%o和%x在C语言中对printf()和scanf()的工作方式不同? [英] Why do the conversion specifiers, %o and %x, work differently for printf() and scanf() in C?

查看:243
本文介绍了为什么转换说明符%o和%x在C语言中对printf()和scanf()的工作方式不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从Stephen Prata的"C Primer Plus"一书中学习C.在第4章中,作者指出在 printf()中,%o和%x分别表示 unsigned 八进制整数和 unsigned 十六进制整数,但是在%o和%x的 scanf()中,分别解释带符号八进制整数和带符号十六进制整数.为什么会这样?

I am learning C from the book "C Primer Plus" by Stephen Prata. In chapter 4, the author states that in printf(), %o and %x, denote unsigned octal integers and unsigned hexadecimal integers respectively, but in scanf(), %o and %x, interpret signed octal integers and signed hexadecimal integers respectively. Why is it so?

我在VS 2015中编写了以下程序来检查作者的陈述:

I wrote the following program in VS 2015 to check the author's statement:

#include <stdio.h>
int main(void)
#pragma warning(disable : 4996)
{
   int a, b, c;

   printf("Enter number: ");
   scanf("%x %x", &a, &b);
   c = a + b;
   printf("Answer = %x\n", c);


   while (getchar() != EOF)
      getchar();
   return 0;
}

代码证明了作者的主张.

The code proved the author's claim.

如果输入具有一对整数,其中正整数的绝对值比负整数的绝对值更大,那么一切正常.

If the inputs had a pair integers where the absolute value of the positive integer was bigger than the absolute value of the negative integer, then everything worked fine.

但是,如果输入有一对整数,其中正整数的绝对值比负整数的绝对值,那么输出就是您希望从 unsigned进行的输出 2的补码.

But if the inputs had a pair integers where the absolute value of the positive integer was smaller than the absolute value of the negative integer, then the output was what you would expect from unsigned 2's complement.

例如:

Enter number: -5 6
Answer = 1

Enter number: -6 5
Answer = ffffffff

推荐答案

C标准指出,对于类似printf的函数(7.21.6.1 fprintf):

The C standard says that for printf-like functions (7.21.6.1 fprintf):

o,u,x,X
unsigned int 参数将转换为unsigned八进制(o),无符号十进制(u)或无符号十六进制表示法(x或X)

o,u,x,X
The unsigned int argument is converted to unsigned octal (o), unsigned decimal (u), or unsigned hexadecimal notation (x or X)

对于类似于scanf的功能,它表示(7.21.6.2 fscanf):

While for scanf-like functions it says (7.21.6.2 fscanf):

x
匹配一个可选的带符号的十六进制整数,其格式相同如预期的对strtoul函数的主题序列具有的值基本参数为16.相应的参数应为指向无符号整数.

x
Matches an optionally signed hexadecimal integer, whose format is the same as expected for the subject sequence of the strtoul function with the value 16 for the base argument. The corresponding argument shall be a pointer to unsigned integer.

因此,作为一项附加功能,您可以编写一个负的十六进制数字,scanf会将其转换为系统格式(二进制补码)的相应无符号数字.

So as an extra feature, you can write a negative hex number and scanf will convert it to the corresponding unsigned number in the system's format (two's complement).

例如

unsigned int x;
scanf("%x", &x); // enter -1
printf("%x", x); // will print ffffffff

为什么他们觉得scanf需要这个适度有用的功能,我不知道.也许是为了与其他转换说明符保持一致.

Why they felt like scanf needed this mildly useful feature, I have no idea. Perhaps it is there for consistency with other conversion specifiers.

但是,由于标准明确指出必须将指针传递给unsigned int,因此本书似乎未正确使用该函数.如果将指针传递给带符号的int,则表示您正在正式调用未定义的行为.

However, the book seems to be using the function incorrectly, since the standard explicitly states that you must pass a pointer to unsigned int. If you pass a pointer to a signed int, you are formally invoking undefined behavior.

这篇关于为什么转换说明符%o和%x在C语言中对printf()和scanf()的工作方式不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆