Portability vs. Endianness

Blair P. Houghton bhoughto at hopi.intel.com
Wed Mar 13 13:26:57 AEST 1991


In article <1991Mar12.105451.19488 at dit.upm.es> esink at turia.dit.upm.es () writes:
>long var;
>unsigned char Bytes[4];
>
>Is there a portable way to move the value held in var
>into the memory space pointed to by Bytes, with the restriction
>that the representation be in Most Significant Byte first
>format ?  I am well aware that sizeof(long) may not be 4.  I

#if (((sizeof long)%(sizeof char)) == 0)	/* even-numbered modulus */
/*
 *  Don't forget; chars _can_ be the same number of bits
 *  as longs, and longs _can_ be an odd number of bytes. 
 *
 *  Give'em an inch, and...
 */

    #define LONGWORD sizeof long
    #define HALFWORD LONGWORD/2

/* Memcpy(3) is the neat way. */

    #include <string.h>

    long var;
    unsigned char Bytes[LONGWORD];
    char *p;

    p = (char *)&var;
    memcpy( (void *)(Bytes+HALFWORD), (void *)p, HALFWORD); /* front to back */
    memcpy( (void *)Bytes, (void *)(p+HALFWORD), HALFWORD); /* back to front */

/* to avoid using p: */

    long var;
    unsigned char Bytes[LONGWORD];

    memcpy((void *)(Bytes+HALFWORD),(void *)&var,HALFWORD); /* front to back */
    memcpy((void *)Bytes,(void *)((char *)&var+HALFWORD),HALFWORD); /*b-f*/

/* but when you don't have the ANSI library or a bcopy(3), */

    long var;
    unsigned char Bytes[LONGWORD];
    char *p;
    int n;

    /* front to back, then back to front */
    for ( p = (char *)&var; p < LONGWORD + (char *)&var; p += HALFWORD )
	for ( n = ((char *)&var + HALFWORD) - p); /* Halfword, then 0 */
	      n < ((char *)&var + LONGWORD) - p); /* Longword, then Halfword */
	      n++ )
	    Bytes[n] = *p;

/*
 *  Of course, since this applies architecturally, you can
 *  wrap it in machine names and simplify until you're silly,
 *  using those porridges of code above only for the default
 *  (unknown wordsize) case.
 */

#ifdef BLEET_TO_BLIT
    /* both: 16-bit chars, 32-bit longs; bleet: little; blit: big */
    long var;
    unsigned char Bytes[2];

    Bytes[0] = *(char *)var;
    Bytes[1] = *((char *)var + 1);
#endif

#endif

The basic answer to your underlying question is, yes, you
can access the individual bytes of any object in ANSI C;
i.e., all objects must have n*CHAR_BIT bits, where n is
some positive integer.  See ANSI X3.159-1989 (i.e., the
standard), sections 1.6 (for "Object"), 2.2.4.2.1 (for
"CHAR_BIT"), and the Rationale, section 1.6 (for more on
the multiples-of-bytes theme).

				--Blair
				  "AND, it has the added BONUS of
				   being able to convert the big-
				   endian BACK into little-endian
				   when you're DONE with it! :-)"



More information about the Comp.lang.c mailing list