Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #107364

Re: Interpret this C code

From Ben Bacarisse <ben.usenet@bsb.me.uk>
Newsgroups comp.lang.c
Subject Re: Interpret this C code
Date 2017-03-29 10:50 +0100
Organization A noiseless patient Spider
Message-ID <87poh0v2cl.fsf@bsb.me.uk> (permalink)
References <ee7d53aa-9688-46e5-9dcb-d2a68cb5f31f@googlegroups.com>

Show all headers | View raw


blackhat401@gmail.com writes:

> I am not a C expert by any means. I would like to understand this
> opensource code below. Can someone please explain the below
> declarations?

The big picture is that they convert a sequence of bytes into integer
types.  The code presumes the bytes are ordered in one of two ways
called big- and little-endian.  This determines whether the first byte
(the one with the lowest address) is the most or the least significant
value byte of the resulting integer.

It might be networking code, since most network protocols use big-endian
and the macros that converts bytes in that format start with "n2"
(network to...?).

> Please advise if there are other ways to self-learn these things for
> future reference.
>
> # define c2l(c,l)        (l = ((unsigned long)(*((c)++)))     , \
>                          l|=(((unsigned long)(*((c)++)))<< 8), \
>                          l|=(((unsigned long)(*((c)++)))<<16), \
>                          l|=(((unsigned long)(*((c)++)))<<24))

There's a slightly odd mixture of too many and too few brackets here.
When not in a macro, this would be written

  l  = (unsigned long)*c++;
  l |= (unsigned long)*c++ <<  8;
  l |= (unsigned long)*c++ << 16;
  l |= (unsigned long)*c++ << 24;

The author has decided to make this a comma expression (essentially the
"one thing after another" way to write what would otherwise be a
sequence of expression statements).  That's a sound idea.

And in a macro, the advice is to put brackets round the whole thing and
round each use of the parameters so I'd write

  ((l)  = (unsigned long)*(c)++,       \
   (l) |= (unsigned long)*(c)++ <<  8, \
   (l) |= (unsigned long)*(c)++ << 16, \
   (l) |= (unsigned long)*(c)++ << 24)

The ()s round l will probably not help at all but it's just simpler to
put them there rather that worry about whether they might matter or not.

The others are all variation on this this theme: extracting the bytes
from an integer or building an integer from constituent bytes.  The
other variations being the sizes of the integers and the order in which
the bytes appear.

In one case, a large integer has been represented as two, presumably for
those implementations that don't have a 64-bit integer type.

> /* NOTE - c is not incremented as per c2l */
> # define c2ln(c,l1,l2,n) { \
>                         c+=n; \
>                         l1=l2=0; \
>                         switch (n) { \
>                         case 8: l2 =((unsigned long)(*(--(c))))<<24; \
>                         case 7: l2|=((unsigned long)(*(--(c))))<<16; \
>                         case 6: l2|=((unsigned long)(*(--(c))))<< 8; \
>                         case 5: l2|=((unsigned long)(*(--(c))));     \
>                         case 4: l1 =((unsigned long)(*(--(c))))<<24; \
>                         case 3: l1|=((unsigned long)(*(--(c))))<<16; \
>                         case 2: l1|=((unsigned long)(*(--(c))))<< 8; \
>                         case 1: l1|=((unsigned long)(*(--(c))));     \
>                                 } \
>                         }

A thing to note is that, in C, the switch statement "falls through", so
here the switch simply determines where to start.  It can, in effect,
read a big-endian integer of any size from 1 to 8 bytes.  (It has a
small technical flaw, in the it is not permitted to decrement a pointer
that poits to the start of an object, an this this macro may do that.
It's rarely a problem in practice.)

<snip>
-- 
Ben.

Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Interpret this C code blackhat401@gmail.com - 2017-03-28 17:50 -0700
  Re: Interpret this C code Jorgen Grahn <grahn+nntp@snipabacken.se> - 2017-03-29 05:43 +0000
  Re: Interpret this C code Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-03-29 10:50 +0100
    Re: Interpret this C code Philip Lantz <prl@canterey.us> - 2017-04-03 00:03 -0700
      Re: Interpret this C code Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-03 21:04 +0100
  Re: Interpret this C code praveen.bochetty@gmail.com - 2017-03-29 17:24 -0700

csiph-web