【问题标题】:How to set the values of an array to a single variable如何将数组的值设置为单个变量
【发布时间】:2019-10-30 04:07:00
【问题描述】:

我正在从 ARM micro 的 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 位整数中。

【问题讨论】:

  • fil 指向什么,为什么要传递它的地址?
  • @M.M 根据文档:FIL* FileObject, /* 指向文件对象结构的指针 */。 fil 被声明为:静态 FIL fil;

标签: c arrays


【解决方案1】:

使用并集,但要记住字节序。

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

typedef 联合 { 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: %s\n", (e = checkEndianess()) == BIG_E ? "BIG":"LITTLE");

    printf("Punned uint64_t for our system 0x%lx\n", arrayToU64(BIG_E_Array, e));
    printf("Punned uint64_t for the opposite endianess system 0x%lx\n", arrayToU64(BIG_E_Array, e == BIG_E ? LITTLE_E : BIG_E));

    return 0;
}

【讨论】:

  • @alk 什么更新?我刚刚编辑。输入数组为大端。onlinegdb.com/SyBKmYQ1r顺序100%OK
  • 顺便说一句:memcpy()memmove() 便宜。
  • 故意的 :) 以防万一有人经过重叠的物体。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    这里要注意的事项:

    1. 字节排序正确
    2. 将这六个字节读入一个 64 位整数

    问题 1 可以通过将网络字节顺序 (Big Endian) 传入的字节存储到主机字节顺序的 64 位整数中来解决,例如使用以下两个宏:

        /* 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. 通过联合使用“Type Punning

      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)
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-07
      • 2016-12-27
      • 2013-05-19
      • 1970-01-01
      • 2021-04-03
      • 2018-10-31
      • 2012-07-10
      相关资源
      最近更新 更多