Network/Host byte ordering and bitfields

Eljay Love-Jensen eljay@adobe.com
Wed Jun 23 22:21:00 GMT 2004


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



More information about the Gcc-help mailing list