Ben Bacarisse
4/20/2011 12:23:00 AM
"Morris Keesan" <mkeesan@post.harvard.edu> writes:
> On Tue, 19 Apr 2011 14:02:21 -0400, Test <test@.nil.invalid.com> wrote:
>
>> I have:
>>
>> int xx;
>> char *buf;
>>
>> buf is pointed to a string with int values, for example:
>>
>> buf=(char *)malloc(4);
>> buf[0]=0;
>> buf[1]=0;
>> buf[2]=178;
>> buf[3]=3;
>> etc.
<snip>
> Avoiding non-portable assumptions about endian-ness and int sizes,
> why not
> xx = (buf[2] << 8) + buf[3];
It's not as simple as that. A couple of posters have suggested that
this is all that is needed, but to avoid assumptions about int sizes you
need to work harder.
(1) char could be signed and buf[2] negative so the shift could be
undefined.
(2) If we make buf unsigned char, it will still probably promote to int
so the arithmetic value of the shift may be unrepresentable in the
result type. That also makes it undefined.
(3) If we cast to unsigned int (i.e. (unsigned int)buf[2] << 8) the
result may be too large to assign to an int without triggering
implementation defined behaviour or (worse) the raising of an
implementation defined signal.
There are, of course, ways round all this but, frankly, I'd write what
you have done 99 times out of 100. I've only had to do this once in a
library that needed to give strong portability assurances, and I did it
your way there too, but that was in K&R1 days so I could just wave my
hands an talk about what will "probably happen on most systems".
All of the above problems assume C99. In C90 ("ANSI C") the wording is
more vague, so while buf[2] << 8 can't be undefined, the exact value of
a signed shift is not 100 clear to me.
<snip>
--
Ben.