Re: Off-topic

Olaf Titz (olaf@bigred.inka.de)
06 Mar 1997 11:05:31 +0100


Richard B. Johnson <root@analogic.com> wrote:
> struct foo {
> short int one __attribute__((packed));
> long int two __attribute__((packed));
> } FOO;
> This returns a length of 6 which is what I want. Bare bones, left to
> gcc's whim, it would return a value of 8 as it quietly aligns the
> longword on a longword boundary. This IS what most people want. However,
> when you are dealing with a serial data-stream, you have to take what
> you get. Of course, you could pretend that the serial data stream was
> a string of bytes, then initialize various kinds of pointers to
> point to various data-elements. That is kind of hokey.

I do the latter thing, because I don't want to depend on gcc (or
rather have to use machines where gcc isn't available).
Here is a SOCKS request structure from this POV:
#define rq_ver(s) ((s)->buf[0])
#define rq_cmd(s) ((s)->buf[1])
#define rq_rsv(s) ((s)->buf[2])
#define rq_atyp(s) ((s)->buf[3])
#define rq_addr(s) (*(struct in_addr *)(((s)->buf)+4))
#define rq_port(s) (*(unsigned short *)(((s)->buf)+8))

where s is a pointer to a struct which contains
unsigned char buf[BUFS];

The code gets rather readable this way.

Beware - both __attribute__((packed)) and this method don't account
for hardware enforced alignment. If it is ever compiled on a system
that requires 8-byte alignment for a struct in_addr (a 4-byte entity)
it will bomb. I don't know if there is such hardware, but I have
already got bus errors on an HP using this technique on a misaligned
short (with the same program). A way around that is something like

#define xx(s) ((((s)->buf[5])<<8)+(s)->buf[6])

if xx is an unsigned short in network order on position 5.

olaf