c - 如何将数组的值设置为单个变量



我正在从 ARM 微型中的 SD 卡读取值:

Res = f_read(&fil, (void*)buf, 6, &NumBytesRead);

其中fil是指针,buf是存储数据的缓冲区。

这就是问题所在:它是一个数组,但我希望将该数组的内容放在一个变量中。

举一个实际的例子:从文件中读取的 6 个字节是:

buf[0] = 0x1B
buf[1] = 0x26
buf[2] = 0xB3
buf[3] = 0x54
buf[4] = 0xA1
buf[5] = 0xCF

我希望有:uint64_t data等于0x1B26B354A1CF.也就是说,数组的所有元素"连接"在一个 64 位整数中。

没有类型双关语,你可以执行以下操作。

uint64_t data = 0;
for (int i=0; i<6; i++)
{
  data <<= 8;
  data |= (uint64_t) buf[i];
}

使用联合,但请记住字节序。

 union 
 {
      uint8_t u8[8];
      uint64_t u64;
  }u64;

Typedef Union{ uint8_t u8[8]; uint64_t U64;}u64;

typedef enum
{
    LITTLE_E,
    BIG_E,
}ENDIANESS;
ENDIANESS checkEndianess(void)
{
    ENDIANESS result = BIG_E;
    u64 d64 = {.u64 = 0xff};
    if(d64.u8[0]) result = LITTLE_E;
    return result;
}
uint64_t arrayToU64(uint8_t *array, ENDIANESS e) // for the array BE
{
    u64 d64;
    if(e == LITTLE_E)
    {
        memmove(&d64, array, sizeof(d64.u64));
    }
    else
    {
        for(int index = sizeof(d64.u64) - 1; index >= 0; index--)
        {
            d64.u8[sizeof(d64.u64) - index - 1] = array[index];
        }
    }
    return d64.u64;
}
int main()
{
    uint8_t BIG_E_Array[] = {0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80};
    ENDIANESS e;
    printf("This system endianess: %sn", (e = checkEndianess()) == BIG_E ? "BIG":"LITTLE");
    printf("Punned uint64_t for our system 0x%lxn", arrayToU64(BIG_E_Array, e));
    printf("Punned uint64_t for the opposite endianess system 0x%lxn", arrayToU64(BIG_E_Array, e == BIG_E ? LITTLE_E : BIG_E));
    return 0;
}

这里要注意的事情:

  1. 正确排序字节
  2. 将六个字节读入一个 64 位整数
问题 1 可以通过将网络字节顺序

(大字节序(中的字节按主机字节顺序存储到 64 位整数中来解决,例如使用以下两个 marcos:

    /* below defines of htonll() and ntohll() are taken from this answer:
       https://stackoverflow.com/a/28592202/694576
     */
    #if __BIG_ENDIAN__
    # define htonll(x) (x)
    # define ntohll(x) (x)
    #else
    # define htonll(x) ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
    # define ntohll(x) ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
    #endif

问题 2 可以通过多种方式解决:

  1. 扩展您的方法

    #define BUFFER_SIZE (6)
    ...
      assert(BUFFER_SIZE <= sizeof (uint64_t)); 
      uint8_t buffer[BUFFER_SIZE];
      FILE * pf = ...; /* open file here */
      /* test if file has been opened successfully here */
      ... result = f_read(pf, buffer, BUFFER_SIZE, ...);
      /* test result for success */
      uint64_t number = 0;
      memset(&number, buffer, BUFFER_SIZE)
      number = ntohll(number);
    
  2. 使用
  3. 联合使用">类型双关语">

    union buffer_wrapper
    {
      uint8_t u8[sizeof (uint64_t)];
      uint64_t u64;
    }
    

    而不是

      uint8_t buffer[BUFFER_SIZE];
    

      union buffer_wrapper buffer;
    

    而不是

      memcpy(&number, buffer, BUFFER_SIZE)
      number = ntohll(number)
    

      number = ntohll(buffer.u64)
    

最新更新