我想通过班次将unsigned char
存储到char
。由于两种数据类型具有相同的长度(我的机器上有1个字节),我希望以下代码可以工作:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int main () {
printf ("%d\n", sizeof(char));
printf ("%d\n", sizeof(unsigned char));
unsigned char test = 49;
char testchar = (char) (test - 127);
printf ("%x\n", testchar);
return 0;
}
但事实并非如此。特别是,我得到了以下输出:
1
1
ffffffb2
表明char已经转换为int
。有没有人有解释,希望是解决方案?
答案 0 :(得分:5)
printf是一个可变参数函数,因此它的参数受默认促销规则的约束。对于这种情况,您的char被提升为int,并在该过程中进行符号扩展。
具有二进制模式0xffffffb2的4字节的2的补码是-78。使用%hhx
说明符将其打印为char。
另见Which integral promotions do take place when printing a char?
答案 1 :(得分:5)
%x
是4字节int
的说明符。要打印一个字节char
,请使用%hhx
。
printf
根据传递给它的格式说明符对其参数进行类型转换。这就是testchar
类型被提升为int
的原因。
答案 2 :(得分:2)
会发生什么!!!!
1)unsigned char test
= 49
; //十六进制值31被分配
2)char testchar = (char) (test - 127);
// 49-127 = -78
ie; 0xb2
{作为unsigned
),将其转换为signed char
结果F
填充b2
之前将其指示为否定
3)printf ("%x\n", testchar);
//由于%x
是4字节int的说明符(因为 @ Do You You Worry Child 表示)ffffffb2
,获得4字节输出
所以请按照 @不要担心孩子说
答案 3 :(得分:1)
%x
仅用于打印unsigned int
,但您提供char
。
使用负值为%x
的{{1}}会导致未定义的行为。
除此之外: char
的C标准规范并不是特别清楚;有些人认为传递除printf
以外的任何内容都会导致未定义的行为。其他人(包括我自己)认为传递非unsigned int
的参数是可以的,但在默认参数促销之后,类型unsigned int
具有非负值。该标准确保非负int
具有与具有相同值的int
相同的表示。
其他一些答案提示unsigned int
,但这并不比%hhx
好。标准(在合理的解释上)指定%x
仅与%hhx
参数一起使用,unsigned char
仅与%hhd
参数一起使用。实际上没有普通signed char
的修饰符。
无论你看哪一种方式,都无法使用char
以明确定义的方式将负值转换为正值表示。您必须自己转换参数,然后使用匹配的格式说明符。在这种情况下:
printf
是一种选择。 IMO printf ("%hhx\n", (unsigned char)testchar);
可以在这里使用,但如上所述,有些人不同意。
NB。在%x
及其后面的行中使用了错误的格式说明符。 printf ("%d\n", sizeof(char));
的说明符为size_t
。所以你可以使用%zu
,或者将参数转换为%zu
,甚至更好:
int
答案 4 :(得分:0)
我希望以下代码能够正常运行:
不会。
忽略其他人如何打印字符所引发的问题,标准中无法保证您的代码能够正常工作。为什么呢?
因为char
不必签名。 char
是signed
还是unsigned
是否依赖于实现。一些实现使char
签名,其他实现使其无符号。
因此,无法保证(char) (test - 127)
会产生可由char
表示的值。
C ++(14)允许在unsigned char
和char
之间进行无损转换。 stadnard说(3.9.1 / 1):
对于0到255(包括0和255)范围内的
unsigned char
类型的每个值i,存在类型char
的值j,使得从i到{{的整数转换(4.7)的结果1}}是j,从j到char
的积分转换结果是i。