Re: Network/Host byte ordering and bitfields

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Marcio,

Here's the short example in GCC's C...

- - - a.h - - - - - - - - - - - - - - - - - -

struct A
{
  unsigned int a : 1;
  unsigned int b : 26;
  unsigned int c : 3;
};  __attribute__((packed));
// WARNING:  If this structure changes,
// change the readStructA and writeStructA routines!

extern void readStructA(int fd, struct A*);
extern void writeStructA(int fd, struct A*);

- - - a.c - - - - - - - - - - - - - - - - - -

#include <stdio.h>
#include <unistd.h>
#include <inttypes.h>

/* I'm going to use file descriptors instead of FILE*. That way, you don't have to know what kind out output you are writing to (e.g., a file, a socket, a pipe, et cetera). Feel free to substitute FILE* and the analogous file functions instead.
*/


/* Canonical Struct A record format
 * byte a[1];
 * byte b[4]; // in agnostic network order
 * byte c[1];
**/

void writeStructA(int fd, struct A* x)
{
  uint8_t item1 = x->a;
  uint32_t item2 = x->b;
  uint8_t item3 = x->c;
  ssize_t err;

  err = write(fd, &item1, sizeof item1);
  if(err != sizeof item1) Kboom();

  item2 = htonl(item2);
  err = write(fd, &item2, sizeof item2);
  if(err != sizeof item2) Kboom();

  err = write(fd, &item3, sizeof item3);
  if(err != sizeof item3) Kboom();

/* If converting to FILE* and related functions, you MAY want a fflush here, and a check to make sure the flush worked. The low level read/write against a file descriptor is normally unbuffered. Except for IP sockets and Nagle's algorithm for buffering packets, but that's a whole 'nother can of worms.
*/
}


// C style slicing takes care of our bit twiddling needs.
// But I'm including masking anyway, just for illustration.
void readStructA(int fd, struct A* x)
{
  uint8_t item1;
  uint32_t item2;
  uint8_t item3;
  ssize_t err;

  err = read(fd, &item1, sizeof item1);
  if(err != sizeof item1) Kboom();
  x->a = item1 & 0x01;

  err = read(fd, &item2, sizeof item2);
  if(err != sizeof item2) Kboom();
  item2 = ntohl(item2);
  x->b = item2 & 0x03FFFFFF;

  err = read(fd, &item3, sizeof item3);
  if(err != sizeof item3) Kboom();
  x->c = item3 & 0x07;
}

// Kboom does something appropriate for handling error situations.

- - - - - - - - - - - - - - - - - - - - -

HTH,
--Eljay


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux