簡體   English   中英

在 C 中解碼帶符號的 CAN 字節

[英]Decoding signed CAN bytes in C

我一直在嘗試編寫一個函數來解碼 C 中的 CAN 字節,同時考慮到傳入值的字節順序和系統的字節順序。 現在,它適用於無符號值,但不適用於有符號值。

我有一種感覺,我深深誤解了 C 中帶符號表示的工作原理——我認為 MSB 是帶符號數據的符號標志(即 Little Endian 的最后一個字節,Big Endian 的第一個字節)。 有人可以看看我下面的功能,讓我知道我做錯了什么嗎?

/**
 * @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 - interpretted 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;
}

問題:

標志延長困境

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 執行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM