将' unsigned char '放入' char '中

Put an `unsigned char` into a `char`

本文关键字:char 放入 unsigned      更新时间:2023-10-16

我想通过移位将unsigned char存储到char中。由于这两种数据类型具有相同的长度(在我的机器上为1字节),我希望下面的代码可以工作:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int main () {
        printf ("%dn", sizeof(char));
        printf ("%dn", sizeof(unsigned char));
        unsigned char test = 49;
        char testchar = (char) (test - 127);
        printf ("%xn", testchar);
        return 0;
}

,但它没有。特别是,我得到了以下输出:

1
1
ffffffb2

表示该字符已被强制转换为int。有人能解释一下吗,希望能解决这个问题?

%x是4字节int的说明符。要打印一个字节的char,使用%hhx

printf根据传递给它的格式说明符对其参数进行类型转换。这就是testchar被提升为int的原因。

printf是一个可变参数函数,因此它的参数受默认提升规则的约束。在这种情况下,您的字符被提升为int型,并在此过程中进行符号扩展。二进制模式为0xffffffb2的4字节2的补码int为-78。使用%hhx说明符将其作为字符打印。

参见在打印字符时发生哪些积分提升?

%x仅用于打印unsigned int,然而您提供了char

使用%xchar的负值会导致未定义的行为。

旁白: printf的C标准规范不是特别清楚;有些人认为传递除了unsigned int之外的任何东西都会导致未定义的行为。其他人(包括我自己)认为传递不明确为unsigned int的参数是可以的,但在默认参数提升之后,具有非负值的int类型。该标准保证非负的int s与具有相同值的unsigned int具有相同的表示。


其他一些答案建议%hhx,但这并不比%x好。标准(根据合理的解释)指定%hhx只能与unsigned char参数一起使用,%hhd只能与signed char参数一起使用。对于普通的char,实际上没有修饰符。

无论您如何看待它,printf都无法以良好定义的方式将负值转换为正表示。必须自己转换实参,然后使用匹配的格式说明符。在本例中:

printf ("%hhxn", (unsigned char)testchar);

是一个选项。IMO %x可以在这里使用,但如上所述,有些人不同意。


NB。在printf ("%dn", sizeof(char));及其后面的行中使用了错误的格式说明符。size_t的指定符为%zu。因此,您可以使用%zu,或将参数强制转换为int,甚至更好:

printf("1n");

发生的事情是!!!!

1) unsigned char test = 49;//十六进制值31被分配

2) char testchar = (char) (test - 127);//49-127 = -78 ie;0xb2(作为unsigned),将其转换为signed char,结果Fb2之前填充以表示它为负

3) printf ("%xn", testchar);//由于%x是4字节整型(如@Don't You Worry Child所说)ffffffb2的说明符,因此得到4字节的输出

所以尽量按照@Don't You Worry Child said

我希望下面的代码可以工作:

它不会。

忽略其他人指出的如何打印字符的问题,在标准中并不能保证您的代码可以正常工作。为什么?

因为char不一定是符号charsigned还是unsigned取决于具体实现。有些实现使char有符号,有些实现使它无符号。

因此,不能保证(char) (test - 127)会产生一个可以由char表示的值。

c++(14)允许unsigned charchar之间的无损转换。标准说(3.9.1/1):

对于0 ~ 255范围内unsigned char类型的每一个值i,存在一个char类型的值j,使得从i到char的整数转换(4.7)的结果为j,从j到unsigned char的整数转换的结果为i。