Path: utzoo!news-server.csri.toronto.edu!rutgers!mcnc!decwrl!world!ksr!jfw From: jfw@ksr.com (John F. Woods) Newsgroups: comp.lang.c Subject: Re: Portability vs. Endianness Message-ID: <2669@ksr.com> Date: 13 Mar 91 19:23:10 GMT References: <1991Mar12.105451.19488@dit.upm.es> <2628@ksr.com> <15457@smoke.brl.mil> Sender: news@ksr.com Lines: 55 [One more time, this time with an open copy of ANSI C] gwyn@smoke.brl.mil (Doug Gwyn) writes: >In article <2628@ksr.com> jfw@ksr.com (John F. Woods) writes: >>This code is guaranteed. >"Famous last words." >In fact, it is not guaranteed on a host that uses ones-complement >or sign-magnitude integral representation. Hmm. Actually, even more offensive is that my code fails if the number of bits in a byte isn't 8 (fails in some sense, anyway; it does (on a 2s-complement 9-bit-per-byte machine) pick up the low 32 bits of the long, which might be what's desired, but it doesn't pick up the low 4xbytesize bits of the long, which might well be the idea). In fact, it isn't "guaranteed" even on a garden-variety, right-thinking, 8-bits-per-byte 2s-complement machine because "if E1 has a signed type and a negative value, the resulting value is implementation-defined." One hopes the compiler will not generate code to launch a nuclear airstrike, but if it is so documented in the vendor's manual, it is OK by ANSI. Further hmm. Is memcpy() obliged to do anything sensible if handed a pointer to an integer cast to a void *? The ANSI C spec refers to memcpy() as working on "arrays of characters", and I know there have been discussions where (for example) integers are placed in a different address space from characters and hence a routine cannot assume that it can make any use of "(char *)&integervalue". Hmm again. Now that I am staring at the ANSI manual, there's lots of fascinating things here. First, a conforming implementation is not required to be able to represent "-0x80000000" in a signed long, but must be able to represent all 0x100000000 32-bit values in an unsigned long. So, I think that the variable definitions should be changed to: unsigned long var; unsigned char Bytes[4]; Then Bytes[0] = (var >> 24) & 0xFF; Bytes[1] = (var >> 16) & 0xFF; Bytes[2] = (var >> 8) & 0xFF; Bytes[3] = var & 0xFF; Ought to give a consistent answer. I think. At least, I think it gives the same answer on a 68000 and a DataBlaster-1000. The problem specification is, I think, the real problem: what, for example, does it really *mean* to "want the value contained in var converted to a 68000 long word" on a 9 bit (or 1s-complement) machine? If the goal is to printf the four bytes with %x, I think the above solution is right in all cases; if the goal is to write the data out on tape, then a 9-bit machine may not be able to give a useful answer in any case. I'm going to put "guarantee" into my spell-checker's list of "always misspelled" words (well, I would if I used one...).