将int(32位)转换为char(8位)

3

我有以下这些定义:

int data = uartBaseAddress[UART_DATA_REGISTER / 4]; // data coming from UART RX port
char message[20]; // array of 20 chars

现在当我尝试这样做时:
message[0] = (char) data;
printf("%x", message[0]);

它会打印出(例如):"ffffff9c"。当然,我只想要最后8位("9c"),但我不知道如何正确地将int转换为char

编辑:我的意思是:我必须像这样填充数组:

data = 0xFFFFFF9c;
message[0] = data & 0xFF; -- it has to contain only 9c
data = 0xFFFFFFde;
message[1] = data & 0xFF; -- it has to contain only de
etc...
2个回答

6
转换结果正确,问题在于printf
显然,在您的系统上,普通的char是有符号的(它可以是有符号或无符号的)。
我猜打印出的值是ffffff9c(8位数字),而不是ffffffff9c(10位数字)。请验证一下。 data的值可能是-100。将该值从int转换为char将产生-100,因为该值在char类型的范围内(可能是-128.. +127)。
但是,%x格式说明符需要一个unsigned int类型的参数,而不是int。当message [0]传递给printf时,其值被提升为int,但是由于格式字符串,printf会假定该参数是unsigned int类型。
严格来说,这种行为是未定义的,但最有可能的是printf将简单地获取传递给它的int值,并将其视为unsigned int(int)-100(unsigned int) 0xffffff9c具有相同的表示形式。
没有printf格式说明符可以以十六进制打印有符号值。如果您将格式从%x更改为%d,则至少会看到正确的值。
但是您应该退后一步,决定您要实现什么。如果您想提取data的低8位,则可以通过屏蔽它来实现,就像unwind的答案所建议的那样。或者,您可以将其转换为unsigned char而不是普通的char,以确保您将获得无符号值。
当将unsigned char值传递给printf时,它仍会被提升为int,因此为了完全正确,您应该显式将其转换为unsigned int
int data = ...;
unsigned char message[20]; // change to unsigned char

message[0] = data;  // no cast needed, the value is implicitly converted
printf("%x", (unsigned int)message[0]);

严格来说,(unsigned int)不是必需的。message [0]是一个unsigned char类型,因此它将被转换为非负的int值,并且有一种特殊情况规则,指出具有相同值的intunsigned int参数在函数参数中是可以互换的。尽管如此,我个人更喜欢使用强制类型转换,因为它更加清晰,而且添加强制类型转换比按照不需要的线路推理要容易(特别是对于任何阅读代码的人来说)。


抱歉出现错误,打印的值为8位数字。感谢您的回答,非常完整和清晰! - HBv6
2
顺便提一下,将类型转换为“unsigned int”并不是必要的。如果“int”覆盖了“unsigned char”的范围,则可以将“int”解释为“unsigned int”(表示相同的值),或者(我不确定这是否符合标准)“UCHAR_MAX”大于“INT_MAX”,在这种情况下,参数将被提升为“unsigned int”。 - mafso
@mafso:没错,但我仍然更喜欢使用强制类型转换;它使代码更清晰,而且比跟随提供它不是必需的推理要容易得多。请参见我更新答案的最后一段。 - Keith Thompson

5

不需要使用message,只需屏蔽您不需要的位:

printf("%x\n", data & 0xff);

将一个32位整数转换为一个由4个8位数字组成的数组,可以执行以下操作:

const uint32_t data = ...
uint8_t message[20];

for(int i = 0; i < 4; ++i)
{
  message[i] = data & 0xff;
  data >>= 8;
}

上述使用了小端字节序。如果data0x12345678,那么message将以0x78, 0x56, 0x34, 0x12开头。


你的建议很好,但如果我需要填充一个字符数组怎么办?我尝试过这样做:message[0] = data & 0xFF; 但它没有起作用... - HBv6
1
如果我每次听到有人说“不起作用”而没有更多上下文信息,我都能得到一枚硬币,那我就会变得富有。 - glglgl
@glglgl 你说得对,我的意思是:在赋值之后,字符数组是否按照我想要的方式填充?如果我这样做:(在for循环中)message[i] = data & 0xFF; - 你确定向量的每个元素都是数据的最后8位吗? - HBv6
如果其他都正确的话,这应该完全按照您所描述的方式工作。 - glglgl

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