Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!mit-eddie!uw-beaver!milton!ogicse!intelhf!ichips!iwarp.intel.com!inews!hopi!bhoughto From: bhoughto@hopi.intel.com (Blair P. Houghton) Newsgroups: comp.lang.c Subject: Re: Portability vs. Endianness Message-ID: <3005@inews.intel.com> Date: 13 Mar 91 03:26:57 GMT References: <1991Mar12.105451.19488@dit.upm.es> Sender: news@inews.intel.com Organization: Intel Corp, Chandler, AZ Lines: 85 In article <1991Mar12.105451.19488@dit.upm.es> esink@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 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! :-)"