解码C语言中的带符号CAN字节

iqjalb3h  于 2022-12-02  发布在  其他
关注(0)|答案(1)|浏览(177)

我一直在尝试用C语言编写一个函数来解码CAN字节,考虑到传入值的字节序和系统的字节序。现在,它对无符号值工作正常,但对有符号值工作不好。
我有一种感觉,我深深地误解了C语言中带符号表示的工作原理--我假设MSB是带符号数据的符号标志(即小端的最后一个字节,大端的第一个字节)。有人能看看下面我的函数,让我知道我做错了什么吗?

/**
 * @brief can_interact_decode - converts array of length x containing hex bytes into a uint64
 * @param[in] const uint8_t* - const array of hex bytes
 * @param[in] const size_t - length of hex bytes array
 * @param[in] const enum can_interact_signedness - whether the bytes are storing a signed value or not. SIGNED_VAL indicates signed, UNSIGNED_VAL indicates unsigned
 * @param[in] const enum can_interact_endianness - endianess. LITTLE_ENDIAN_VAL is little, BIG_ENDIAN_VAL is big
 * @return[out] uint64_t - interpreted value as unsigned int from hex bytes, taking other params into account
 */
uint64_t can_interact_decode(const uint8_t *payload, const size_t data_len, const enum can_interact_signedness is_signed, const enum can_interact_endianness byte_order)
{
    uint64_t result; /* [0,0,0,0,0,0,0,0] */
    uint8_t* blocks; /* array of 8 */
    result = 0;
    blocks = (uint8_t*)(&result);

    if(byte_order == LITTLE_ENDIAN_VAL) {
        memcpy(blocks, payload, (is_signed ? data_len - 1 : data_len));
        blocks[7] = is_signed ? payload[data_len - 1] : blocks[7];
        result = le64toh(result); /* little endian->host byte order */
    } else if(byte_order == BIG_ENDIAN_VAL) {
        memcpy(blocks + (8 - data_len) + (is_signed ? 1 : 0), (is_signed ? payload + 1 : payload), (is_signed ? data_len - 1 : data_len));
        blocks[0] = is_signed ? payload[0] : blocks[0];
        result = be64toh(result); /* big endian->host byte order */
    }

    return result;
}
disho6za

disho6za1#

问题:
“悲伤的征兆"
OP似乎想要将符号 * 位 * 符号扩展到其他 * 字节 * 中。

if(byte_order == LITTLE_ENDIAN_VAL) {
    //memcpy(blocks, payload, (is_signed ? data_len - 1 : data_len));
    //blocks[7] = is_signed ? payload[data_len - 1] : blocks[7];
    memcpy(blocks, payload, data_len);
    if (is_signed && ((const int8_t*)payload)[data_len - 1] < 0) {
      memset(blocks + data_len, 0xFF, 8 - data_len);
    }  
    result = le64toh(result); /* little endian->host byte order */

我将在else if(byte_order == BIG_ENDIAN_VAL)块中进行类似的更改,以便OP执行。

相关问题