将一个`unsigned char`放入`char`中

5
我希望通过移位将一个无符号字符存储到一个字符中。由于这两种数据类型在我的计算机上具有相同的长度(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。有没有人能够解释一下,并且希望能提供一个解决方案?


我猜它“崩溃”是因为%x。你试过%d了吗? - Jasper
无论是在所有情况下使用printf %x还是%d,您都可以看到十进制和十六进制的值。 - DrakaSAN
我完全不明白你为什么要减去127,而且我认为你在问题中没有解释这种方法真是太可惜了。 - Lightness Races in Orbit
顺便提一下,sizeof(char)保证为1。 - Trevor Hickey
使用%zu来打印size_t。使用错误的格式说明符,如%d会引发未定义的行为。 - phuclv
5个回答

5

printf是一个可变参数函数,因此它的参数受到默认提升规则的影响。在这种情况下,char类型会被提升为int类型,并在此过程中进行符号扩展。

具有二进制模式0xffffffb2的4字节2's补码整数是-78。使用%hhx说明符将其作为char类型打印出来。

另请参阅哪些积分晋升会在打印char时发生?


5

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

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


2

%x只适用于打印unsigned int,但您提供了一个char

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

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


其他答案中提到了%hhx,但这并不比%x更好。标准(在合理的解释下)指定%hhx仅与unsigned char参数一起使用,%hhd仅与signed char参数一起使用。实际上,没有修饰符适用于普通的char

无论如何,不能使用printf以定义良好的方式将负值转换为正表示形式。您必须自己转换参数,然后使用匹配的格式说明符。在这种情况下:

printf ("%hhx\n", (unsigned char)testchar);

一个选项是使用 %x,但正如上面提到的,有些人持不同意见。


注意,在 printf ("%d\n", sizeof(char)); 和其后一行中使用了错误的格式说明符。 size_t 的说明符是 %zu。因此,您可以使用 %zu,或将参数强制转换为 int,甚至更好的做法是:

printf("1\n");

2

发生的情况是 !!!!

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

2) char testchar = (char) (test - 127); // 49-127 = -780xb2 (作为unsigned),将其转换为signed char,结果为在b2前填充F以表示它为负数

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

因此,请按照@Don't You Worry Child所说尝试


0
我本来以为以下代码可以工作:
它不会。
忽略其他人指出的你如何打印字符的问题,标准中没有保证你的代码能够工作。为什么?
因为char不一定是有符号的。char是有符号还是无符号取决于实现。有些实现使char带符号,而另一些则使其无符号。
因此,不能保证(char)(test-127)将产生一个可以由char表示的值。
C++(14)允许在unsigned char和char之间进行无损转换。标准规定(3.9.1/1):
对于类型为unsigned char的每个值i,其范围在0到255之间(包括0和255),都存在一个类型为char的值j,使得从i到char的整数转换(4.7)的结果是j,并且从j到unsigned char的整数转换的结果是i。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接