【问题标题】:Convert int (32 bits) to char (8 bits)将 int(32 位)转换为 char(8 位)
【发布时间】:2014-07-25 07:13:06
【问题描述】:

我有这些定义:

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”),我不明白如何正确地进行从 intchar 的转换。

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

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...

【问题讨论】:

    标签: c arrays char int type-conversion


    【解决方案1】:

    不需要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 字节顺序。如果data0x12345678,那么message 将开始于0x78, 0x56, 0x34, 0x12

    【讨论】:

    • 你的建议很好,但是如果我必须填充一个字符数组呢?我试着做:message[0] = data & 0xFF;但它没有用......
    • @PierpaoloBagnasco 如果每次有人在没有更多上下文的情况下说“没有工作”时我都能得到一角钱,我会很富有。
    • @glglgl 你说得对,我的意思是:在分配之后,char 数组会像我想要的那样填充吗?如果我这样做:(在 for 循环中)message[i] = data & 0xFF; - 你确定向量的每个元素都是最后 8 位数据吗?
    • @PierpaoloBagnasco 如果其他一切都正确,这应该完全按照您描述的方式工作。
    【解决方案2】:

    转换正确。问题出在printf

    显然char 已在您的系统上签名(可以签名或未签名)。

    我猜打印的值是ffffff9c(8 位),而不是ffffffff9c(10 位);请确认。

    data 的值可能是-100。将该值从int 转换为char 将产生-100,因为该值在char 类型的范围内(可能是-128 ..+127)。

    %x 格式说明符需要unsigned int 类型的参数,而不是intmessage[0] 的值在传递给printf 时提升为int,但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 值在传递给 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位。感谢您的回答,非常完整和清晰!
    • 附带说明,unsigned int 的强制转换不是必需的。 int 覆盖 unsigned char 的范围,在这种情况下,int 可以解释为 unsigned int(表示相同的值)或(我不确定这是否符合标准)UCHAR_MAX 是大于INT_MAX,在这种情况下,参数将被提升为unsigned int
    • @mafso:是的,但我还是更喜欢使用演员表;它使代码更清晰,并且比遵循提供不必要的推理要容易得多。请参阅我更新答案的最后一段。
    猜你喜欢
    • 2021-12-16
    • 2013-04-03
    • 1970-01-01
    • 2016-07-27
    • 2015-06-21
    • 2020-10-30
    • 2018-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多