我有这些定义:
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...
答案 0 :(得分:5)
转换是正确的。这是printf
问题。
显然,您的系统上已签署了char
个简单{可以是签名或未签名的。)
我猜测打印的值是ffffff9c
(8位数),而不是ffffffff9c
(10位数);请验证。
data
的值可能是-100
。将该值从int
转换为char
会产生-100
,因为该值在char
类型的范围内(可能是-128
.. {{1} })。
但+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
后,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
具有相同值的参数可作为函数参数互换。尽管如此,我自己的偏好是使用强制转换,因为它更清晰,并且因为添加强制转换更容易(特别是对于阅读代码的任何人),而不是遵循说明没有必要的推理线。
答案 1 :(得分:4)
不需要message
,只需掩盖您不想要的内容:
printf("%x\n", data & 0xff);
要将32位整数转换为8位数的4元素数组,请执行:
const uint32_t data = ...
uint8_t message[20];
for(int i = 0; i < 4; ++i)
{
message[i] = data & 0xff;
data >>= 8;
}
以上使用little-endian字节顺序。如果data
为0x12345678
,则message
将开始0x78, 0x56, 0x34, 0x12
。