我有这些定义:
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...
最佳答案
转换是正确的。这是printf
那就是问题所在。
显然很普通 char
已在您的系统上签名(可以签名或未签名)。
我猜想打印的值是 ffffff9c
(8 位数字),不是 ffffffff9c
(10 位数字);请确认。data
的值可能是 -100
.从 int
转换该值至 char
将产生 -100
,因为该值在类型 char
的范围内(可能是 -128
.. +127
)。
但是%x
格式说明符需要类型为 unsigned int
的参数, 不是 int
. message[0]
的值晋升为 int
当它传递给 printf
, 但是 printf
,由于格式字符串,假设参数的类型为 unsigned int
.
严格来说,行为是未定义的,但很可能 printf
将简单地采取 int
传递给它的值并将其视为 unsigned int
. (int)-100
和 (unsigned int)0xffffff9c
具有相同的表示。
没有printf
格式说明符以十六进制打印有符号值。如果您从 %x
更改格式至 %d
,您至少会看到正确的值。
但是你应该退一步决定你想要完成的事情。如果要提取data
的低8位,你可以通过屏蔽它来实现,如 unwind's answer建议。或者您可以将其转换为 unsigned char
而不是简单的char
以保证您将获得一个无符号值。
安 unsigned char
value 仍然提升为 int
当传递给 printf
,因此要完全正确,您应该明确将其转换为 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
值,并且有一个特殊情况规则说 int
和 unsigned int
具有相同值的参数可以作为函数参数互换。不过,我个人更喜欢使用强制转换,因为它更清晰,并且因为添加强制转换比遵循没有必要的推理路线更容易(特别是对于阅读代码的任何人)。
关于将 int(32 位)转换为 char(8 位),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24040780/