Jan Parzydło
Jan Parzydło

Reputation: 367

read two bytes at once from a byte array in C

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?

Upvotes: 2

Views: 4772

Answers (2)

alk
alk

Reputation: 70931

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);
 }

Upvotes: 0

iBug
iBug

Reputation: 37227

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).

Upvotes: 9

Related Questions