【问题标题】:read two bytes at once from a byte array in C从 C 中的字节数组一次读取两个字节
【发布时间】:2017-12-27 13:40:56
【问题描述】:

假设我有以下字节数组:

uint8_t barr[4] = {0xCE, 0xCE, 0xCE, 0xCE};

给定一个索引n,我希望能够读取两个字节:

uint16_t d16 = barr[0];

并且有d16等于

0xCECE

也许标准库中有一个函数可以执行这样的任务?

【问题讨论】:

  • 所有样本值都相同。 0x01, 0x02 应该与 0x01020x0201 配对吗?你知道你自己系统的数据的字节序吗?

标签: c arrays memory


【解决方案1】:

小菜一碟:

memcpy(&d16, barr + n, sizeof(d16));

不要尝试转换指针或使用unions。这些要么是未定义的行为,要么可能会触发陷阱表示。 memcpy() 是“规范”解决方案(就像 C++ boost 库所做的那样)。

【讨论】:

  • 明智的,一个简单而充分的答案。
  • @JanParzydło 不是那么容易,您应该阅读有关字节序的内容。考虑具有不同值的样本 { 0x11, 0x12, 0x13, 0x14 }
  • 为什么在做 C 的时候 boost 是一个引用?
  • @alk 这在 C 和 C++ 中都是一样的。
  • @alk 很好。 I have to agree.
【解决方案2】:

这里采用线性和字节序安全的方法:

#include <stdint.h>
#include <stdio.h>
#include <arpa/inet.h> /* for ntohs() */

union Convert
{
  uint16_t  to_integer_big_endian;
  uint8_t barr[sizeof (uint16_t)];
};

uint16_t pick_and_convert(uint8_t * barr, size_t s, size_t n)
{
  union Convert c = {0};  /* Take out-of-bound bytes as 0s. */

  for (size_t i = 0; i < sizeof c.barr && (n + i) < s; ++i)
  {
    c.barr[i] = barr[n + i];
  }

  return ntohs(c.to_integer_big_endian);
}

int main(void)
{
   uint8_t barr[4] = {1, 2, 3, 4}; /* Assuming a binary sequence. */
   size_t n;

   scanf("%zu", &n);

   uint16_t to_integer = pick_and_convert(barr, sizeof barr / sizeof *barr, n);

   printf("result = 0x%hx\n", to_integer);
 }

【讨论】:

  • endianness-save 还是 endianness-safe?跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-01
  • 1970-01-01
  • 2021-03-07
相关资源
最近更新 更多