Path: utzoo!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!zaphod.mps.ohio-state.edu!rpi!uupsi!cmcl2!kramden.acf.nyu.edu!brnstnd From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein) Newsgroups: comp.lang.c Subject: Re: Portability vs. Endianness Message-ID: <1291:Mar1304:42:0591@kramden.acf.nyu.edu> Date: 13 Mar 91 04:42:05 GMT References: <1991Mar12.105451.19488@dit.upm.es> Organization: IR Lines: 57 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 ? Portable questions may have unportable answers, but unportable questions can never have portable answers. In other words, ``Most Significant Byte first format (of longs in a 4-byte field)'' is not a portable concept, so there is no way that portable code can implement the format. Now what you probably mean is that Bytes[0] should contain the low 8 bits of var, Bytes[1] should contain the next 8 bits, etc. Literally: Bytes[0] = ((unsigned long) var) & 255; Bytes[1] = (((unsigned long) var) >> 8) & 255; Bytes[2] = (((unsigned long) var) >> 16) & 255; Bytes[3] = (((unsigned long) var) >> 24) & 255; (You should use unsigned to keep the sign bit out of the way.) If (unsigned long) var is between 0 and 2^32 - 1, then you can recover var as var = (long) (((((((unsigned long) Bytes[3]) * 256 + Bytes[2]) * 256) + Bytes[1]) * 256) + Bytes[0]); I think this is machine-independent. But there are no guarantees that long has 32 bits, or that char has 8 bits. In practice, if you can assume that longs are 32 bits and chars are 8 bits, you don't want to write code like the above to do simple byte copies. Some people will suggest #ifdefs. If you want to avoid the #ifdefs, you might find an alternate strategy useful; I quote from my snuffle.c: WORD32 tr[16] = { 50462976, 117835012, 185207048, 252579084, 319951120, 387323156, 454695192, 522067228, 589439264, 656811300, 724183336, 791555372, 858927408, 926299444, 993671480, 1061043516 } ; ... register unsigned char *ctr = &tr[0]; ... x[n] = h[n] + m[ctr[n & 31]]; Here WORD32 is a 32-bit type, and m is a char (actually unsigned char) pointer, really pointing to an array of WORD32s. m[ctr[0]] will on most 32-bit architectures be the low 8 bits of the first WORD32; m[ctr[1]] will be the next 8 bits; and so on. This works because every common byte order---1234, 4321, 2143, 3412---is an invertible permutation of 1234. (I suppose it would be clearer to write the tr[] values in hex, but the magic numbers are more fun.) ---Dan