[英]Why does the binary value of my char change when using %u?
char a = 0b11111111;
printf("%u", a);
We are storing in a signed char (in gcc default char is signed) 1111 1111, meaning -1.我们存储在一个带符号的字符中(在 gcc 默认字符是有符号的)1111 1111,意思是 -1。 But we print with %u, so printf should see 0000 0000 0000 0000 0000 0000 1111 1111.
但是我们使用 %u 打印,所以 printf应该看到 0000 0000 0000 0000 0000 0000 1111 1111。
This number, with two's complement or without - is 255. So why am I getting (2^32 - 1)?这个数字,有或没有补码 - 是 255。那么为什么我得到 (2^32 - 1)? Seems like instead of putting leading zeros (like I expected) the program put leading ones.
似乎程序没有放置前导零(就像我预期的那样),而是放置了前导零。
There are multiple problems in your example:您的示例中有多个问题:
char a = 0b11111111;
uses an extension for binary literals.使用二进制文字的扩展。
char a = 0b11111111;
has implementation defined behavior if char
is signed and CHAR_MAX < 255
.如果
char
已签名且CHAR_MAX < 255
,则具有实现定义的行为。
printf("%u", a)
has undefined behavior because the char
value a
is promoted to int
when passed to printf
, which expects an unsigned int
for the format %u
. printf("%u", a)
具有未定义的行为,因为char
值a
在传递给printf
时被提升为int
,它需要格式为%u
的unsigned int
。
One exception is the rare architectures (mostly DSPs) where char
is unsigned by default and has the same size as unsigned int
.一个例外是罕见的架构(主要是 DSP),其中
char
默认是无符号的,并且具有与unsigned int
相同的大小。 But then char
is not signed and your example does not pose a problem.但是然后
char
没有签名,您的示例不会造成问题。
If you want to print the exact value of type unsigned char
, you should use %hhu
, or use %u
and cast the argument as (unsigned char)
如果要打印
unsigned char
类型的确切值,则应使用%hhu
,或使用%u
并将参数转换为(unsigned char)
As @Lundin stated conversion rules apply正如@Lundin 所述,转换规则适用
to print correctly:正确打印:
printf("%hhu\n", (unsigned char)a);
printf("%u\n", (unsigned char)a);
printf("%"PRIu8"\n", (uint8_t)a);
First of all, char
may be signed or unsigned depending on compiler and is therefore unsuitable for storying raw binary, see Is char signed or unsigned by default?首先,
char
可能是有符号或无符号的,具体取决于编译器,因此不适合记录原始二进制文件,请参阅Is char signed or unsigned by default? . .
In your case it is apparently signed, in which case the value 0b11111111 = 255 won't fit.在您的情况下,它显然已签名,在这种情况下,值 0b11111111 = 255 将不适合。 Upon assignment, 255 will get implicitly converted to the
signed char
in a compiler-specific way.分配后, 255 将以特定于编译器的方式隐式转换为有
signed char
。 Very likely as the 2's complement number -1
.很可能作为 2 的补码
-1
。
Now as you pass any small integer type to printf
, they get implicitly promoted by an oddball rule called default argument promotions , which applies to all variable number of argument functions.现在,当您将任何小的 integer 类型传递给
printf
时,它们会被称为默认参数提升的奇怪规则隐式提升,该规则适用于所有可变数量的参数函数。 This rule goes:这条规则是:
the integer promotions are performed on each argument, and arguments that have type float are promoted to double
对每个参数执行 integer 提升,并且具有浮点类型的 arguments 提升为双精度
For the meaning of "small integer type" and integer promotion, please check Implicit type promotion rules .关于“小 integer 类型”和 integer 提升的含义,请查看隐式类型提升规则。
This means that what's passed to printf
is an int
, still with value -1 but sign extended .这意味着传递给
printf
的是一个int
,其值仍为 -1 但符号为 extended 。 Since int
is likely something like 4 byte, it now contains the raw binary 0xFFFFFFFF instead of just 0xFF.由于
int
可能类似于 4 字节,它现在包含原始二进制 0xFFFFFFFF 而不仅仅是 0xFF。 Which is still the decimal number -1
, just a larger type.这仍然是十进制数
-1
,只是一个更大的类型。
Then finally you tell printf
to print it as unsigned int
, so it gets converted by printf
to the unsigned representation of 0xFFFFFFFF
.然后最后告诉
printf
将其打印为unsigned int
,因此它由printf
转换为0xFFFFFFFF
的无符号表示。 This is a well-defined conversion (C17 6.3.1.3):这是一个定义明确的转换(C17 6.3.1.3):
Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
否则,如果新类型是无符号的,则在新类型可以表示的最大值的基础上重复加减一,直到该值在新类型的范围内。
And you will end up with 2^32 - 1 = 4294967295 on a 32 bit int
computer.在 32 位
int
计算机上,您最终会得到 2^32 - 1 = 4294967295。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.