-4

I need some help in understanding this code of C. I don't know what "L" and "\" is here? Please illustrate a little bit too :)

#define l2n(l,c)        (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \
                         *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
                         *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
                         *((c)++)=(unsigned char)(((l)     )&0xff))

All help is welcome :)

Awais Hussain
  • 392
  • 1
  • 11
  • 25
  • 8
    L means long. \ escapes ending the macro. – IdeaHat Dec 19 '14 at 14:51
  • l is the first parameter of your macro. – OldProgrammer Dec 19 '14 at 14:54
  • 1
    It's just a macro which writes a 4 byte value (`l`) to the buffer pointed at by `c`, in *big endian* order (i.e. most significant byte first). The `c` pointer is also incremented by 4 bytes. – Paul R Dec 19 '14 at 14:57
  • Where is this code from? It seems to try triggering conversion to at least `long` if `l` has a smaller rank, which isn't possible like that in ISO C (but was possible in K&R C iirc, so it might be old code.) – mafso Dec 19 '14 at 14:58
  • The `L` in `24L` makes 24 a `long` rather than `int` constant. It serve no purpose to use it here as it does not affect the type of the result. This is a poor macro. – chux - Reinstate Monica Dec 19 '14 at 15:04
  • @chux: Yes, but where does it make any difference in the code shown? – mafso Dec 19 '14 at 15:05
  • @mafso It makes no difference. Suspect the author thought it would insure that `l` is converted to `long`, but it does not do that. – chux - Reinstate Monica Dec 19 '14 at 15:07
  • 2
    @chux, yes, this was my thought as well. Afair, this really worked in K&R (`1 << 1L` was of type `long` like `1 + 1L` is in ISO C), which is why I asked where the code is from... – mafso Dec 19 '14 at 15:16
  • @harper I am not clear about your comment. What does `L` have to do with any including or omitting any casts? – chux - Reinstate Monica Dec 19 '14 at 16:17
  • [What does the "L" mean at the end of an integer literal?](http://stackoverflow.com/questions/2958007/what-does-the-l-mean-at-the-end-of-an-integer-literal) – phuclv Dec 19 '14 at 18:18
  • @Lu'u The L indicates the preceeding number as a LONG value. Since you can't shift much more thsn 64 bit positions the L is superflous here. – harper Dec 20 '14 at 17:36

1 Answers1

1

This illustrates how a big-endian value is written on my little-endian machine. More explanation: the &0xff part masks off all except the least signifcant 8 bits of the shifted value, although as I am unsure whether that or the (unsigned char) are strictly necessary, I included a macro n2n() without them as a comparison. Without them, I get no compiler warning and no error.

Also I have omitted the L discussed in comments above. Note too that the pointer used must be an unsigned char type - if it was an unsigned int type, c would be incremented by 4 (32-bit architecture). That's why I have used a union to overlay the bytes.

The macro definition must have no space between its identifier and the first bracket. And finally if there seem to be more brackets than necessary in the macros, it is to ensure that any expression is correctly compiled, for example l2n(a+b,c);

#include <stdio.h>

#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
                  *((c)++)=(unsigned char)(((l)>>16)&0xff), \
                  *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
                  *((c)++)=(unsigned char)(((l)    )&0xff))

#define n2n(l,c) (*((c)++)=(l)>>24, \
                  *((c)++)=(l)>>16, \
                  *((c)++)=(l)>> 8, \
                  *((c)++)=(l)    )
typedef union {
    unsigned num;
    unsigned char arr[4];
    } bigend;

int main (void)
{
    bigend number;
    unsigned x;
    char *p;

    // test first macro
    x = 0x12345678;
    p = number.arr;
    printf ("Input  %08X\n", x);
    l2n(x,p);
    printf ("Output %08X\n\n", number.num);

    // test second macro
    x = 0x89ABCDEF;
    p = number.arr;
    printf ("Input  %08X\n", x);
    n2n(x,p);
    printf ("Output %08X\n\n", number.num);
    return 0;
}

Program output:

Input  12345678
Output 78563412

Input  89ABCDEF
Output EFCDAB89
Weather Vane
  • 33,872
  • 7
  • 36
  • 56