2

Let's say I have the following array of bytes:

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

Given an index n, I want to be able to read two bytes:

uint16_t d16 = barr[0];

And have d16 be equal to

0xCECE

Perhaps there is a function in the standard library that can perform such task?

iBug
  • 35,554
  • 7
  • 89
  • 134
Jan Parzydło
  • 367
  • 4
  • 15
  • 2
    All of your sample values are the same. Should `0x01, 0x02` be paired as `0x0102` or as `0x0201`? Do you know the endianness of the data *and* of your own system? – Jongware Dec 27 '17 at 13:49

2 Answers2

9

A piece of cake:

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

Don't try to convert pointers or use unions. Those either are undefined behaviors, or may trip trap representations. memcpy() is the "canonical" solution (as the C++ boost library does).

iBug
  • 35,554
  • 7
  • 89
  • 134
0

A linear and endianness-safe approach here:

#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);
 }
alk
  • 69,737
  • 10
  • 105
  • 255