C语言 无符号字符的格式说明符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27547377/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 11:37:57  来源:igfitidea点击:

Format specifier for unsigned char

c

提问by

Say I want to print unsigned char:

说我想打印unsigned char

unsigned char x = 12;

which is correct. This:

哪个是正确的。这个:

printf("%d",x);

or this:

或这个:

printf("%u",x);

?

?

The thing is elsewhere on SO I encountered such discussion:

事情在其他地方所以我遇到了这样的讨论:

-Even with ch changed to unsigned char, the behavior of the code is not defined by the C standard. This is because the unsigned char is promoted to an int (in normal C implementations), so an int is passed to printf for the specifier %u. However, %u expects an unsigned int, so the types do not match, and the C standard does not define the behavior

- 即使将 ch 更改为 unsigned char,代码的行为也未由 C 标准定义。这是因为 unsigned char 被提升为 int(在普通的 C 实现中),因此 int 被传递给 printf 以用于说明符 %u。但是,%u 需要一个 unsigned int,因此类型不匹配,并且 C 标准没有定义行为

-Your comment is incorrect. The C11 standard states that the conversion specifier must be of the same type as the function argument itself, not the promoted type. This point is also specifically addressed in the description of the hh length modifier: "the argument will have been promoted according to the integer promotions, but its value shall be converted to signed char or unsigned char before printing"

- 你的评论不正确。C11 标准规定转换说明符必须与函数参数本身的类型相同,而不是提升的类型。这一点在 hh 长度修饰符的描述中也有具体说明:“参数将根据整数提升进行提升,但其值应在打印前转换为有符号字符或无符号字符”

So which is correct? Any reliable source saying on this matter? (In that sense we should also print unsigned shortint with %d because it can be promoted to int?).

那么哪个是正确的?有没有可靠的消息来源说这件事?(从这个意义上说,我们也应该unsigned short用 %d打印int,因为它可以提升为int?)。

采纳答案by Grzegorz Szpetkowski

The correct one is*:

正确的是*:

printf("%d",x);

This is because of default argument promotionsas printf()is variadic function. This means that unsigned charvalue is always promoted to int.

这是因为默认参数提升以及printf()可变参数函数。这意味着unsigned charvalue 始终提升为int

From N1570 (C11 draft) 6.5.2.2/6Function calls(emphasis mine going forward):

从 N1570(C11 草案)6.5.2.2/6函数调用(强调我的未来):

If the expression that denotes the called function has a type that does not include a prototype, the integer promotionsare performed on each argument, and arguments that have type floatare promoted to double. These are called the default argument promotions.

如果表示被调用函数的表达式的类型不包含原型,则对每个参数执行整数提升,并将具有类型的参数float提升为 double。这些称为默认参数提升

and 6.5.2.2/7subclause tells:

6.5.2.2/7子条款说:

The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments.

函数原型声明符中的省略号表示在最后一个声明的参数之后停止参数类型转换。该参数默认晋级是在尾随参数执行

These integer promotions are defined in 6.3.1.1/2Boolean, characters, and integers:

这些整数提升在6.3.1.1/2Boolean、characters 和 integers中定义:

If an intcan represent all values of the original type(as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.58)All other types are unchanged by the integer promotions.

如果 anint可以表示原始类型的所有值(受宽度限制,对于位域),则将该值转换为int; 否则,它被转换为unsigned int。这些被称为 整数提升.58)所有其他类型都不受整数提升的影响。

This quote answers your second question of unsigned short(see comment below).

这句话回答了你的第二个问题unsigned short(见下面的评论)。



* with exception to more than 8 bits unsigned char(e.g. it might occupy 16 bit), see @chux's answer.

* 除了超过 8 位unsigned char(例如它可能占用 16 位),请参阅@chux 的回答

回答by chux - Reinstate Monica

Correct format specifier for unsigned char x = 12depends on a number of things:

正确的格式说明符unsigned char x = 12取决于许多因素:

If INT_MAX >= UCHAR_MAX, which is often the case, use "%d". In this case an unsigned charis promoted to int.

如果INT_MAX >= UCHAR_MAX,通常是这种情况,请使用"%d"。在这种情况下, anunsigned char被提升为int

printf("%d",x);

Otherwise use "%u"(or "%x", "%o"). In this case an unsigned charis promoted to unsigned.

否则使用"%u"(或"%x", "%o")。在这种情况下, anunsigned char被提升为unsigned

printf("%u",x);

Up-to-date compilers support the "hh"length modifier, which compensates for this ambiguity. Shouldxget promoted to intor unsigneddue to the standard promotions of variadic parameters, printf()converts it to unsigned charbefore printing.

最新的编译器支持"hh"长度修饰符,它弥补了这种歧义。应该x被提升intunsigned由于可变参数的标准提升,在打印之前printf()将其转换为unsigned char

printf("%hhu",x);

If dealing with an old compiler without "hh"or seeking highly portable code, use explicit casting

如果处理没有"hh"或寻求高度可移植代码的旧编译器,请使用显式转换

printf("%u", (unsigned) x);


The same issue/answer applies to unsigned short, expect INT_MAX >= USHRT_MAXand use "h"instead of "hh".

相同的问题/答案适用于unsigned short、expectINT_MAX >= USHRT_MAX和 use"h"而不是"hh"

回答by mafso

Both, unsigned charand unsigned short, can always safely be printed with %u. Default argument promotions convert them either to intor to unsigned int. If they are promoted to the latter, everything is fine (the format specifier and the type passed match), otherwise C11 (n1570) 6.5.2.2 p6, first bullet, applies:

这两种,unsigned char而且unsigned short,总是可以安全地打印%u。默认参数提升将它们转换为intunsigned int。如果它们被提升为后者,一切都很好(格式说明符和传递的类型匹配),否则 C11 (n1570) 6.5.2.2 p6,第一个项目符号,适用:

  • one promoted type is a signed integer type, the other promoted type is the corresponding unsigned integer type, and the value is representable in both types;
  • 一个提升类型是有符号整数类型,另一个提升类型是对应的无符号整数类型,值在两种类型中都可以表示;

The standard is quite clear that default argument promotions apply to the variadic arguments of printf, e.g. it's mentioned again for the (mostly useless) hand hhlength modifiers (ibid. 7.21.6.1 p7, emph. mine):

标准很清楚,默认参数提升适用于 的可变参数printf,例如,再次提到了(大部分无用)hhh长度修饰符(同上。7.21.6.1 p7,emph。我的):

hh-- Specifies that a following d, i, o, u, x, or Xconversion specifier applies to a signed charor unsigned charargument (the argument will have been promoted according to the integer promotions, but its value shall be converted to signed charor unsigned charbefore printing); [...]

hh-- 指定后面的d, i, o, u, x, orX转换说明符适用于signed charorunsigned char参数(该参数将根据整数提升进行提升,但其值应转换为signed charunsigned char之前打印);[...]

回答by IdeaHat

For cross platform development, I typically bypass the promoting issue by using inttypes.h

对于跨平台开发,我通常通过使用绕过推广问题 inttypes.h

http://pubs.opengroup.org/onlinepubs/009695399/basedefs/inttypes.h.html

http://pubs.opengroup.org/onlinepubs/009695399/basedefs/inttypes.h.html

This header (which is in the C99 standard) defines all the printf types for the basic types. So if you want an uint8_t (a syntax which I highly suggest using instead of unsigned char) I would use

这个头文件(在 C99 标准中)定义了基本类型的所有 printf 类型。所以如果你想要一个 uint8_t(我强烈建议使用的语法而不是无符号字符),我会使用

#include <inttypes.h>
#include <stdint.h>
uint8_t x;
printf("%" PRIu8 "\n",x);