On 18 Mar, 03:23, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> If you can, avoid using signed binary numbers as a portable
> representation
Unfortunately I can't avoid it, because the data packet format
is fixed not by me.
> but if you can't you can read the two bytes and pack
> them into an unsigned int:
So you agree with me that the two reading instructions can't work with
signed values on 32 bits machines.
I found the same code on Question 12.42 of comp.lang.c FAQ ("How can I
write code to conform to these old, binary data file formats?"). There
the following struct is defined:
struct mystruct {
char c;
long int i32;
int i16;
} s;
and the following code is used to read the 16 bits value:
s.i16 = getc(fp) << 8;
s.i16 |= getc(fp);
If we assume the values stored in the file are unsigned (0-65535), the
member i16 should had be defined as unsigned int (not signed int),
otherwise the value 40000 can't be correctly received on 16-bits
machines.
If we assume the values stored in the file are signed (-32767 -
+32767), the code to read them doesn't work for negative values on
implementations with int size greater than 16 bits (the value -1 is
written in the file as 0xFF 0xFF, but is read back as 65535 on 32-bits
platforms).
In both cases, the code doesn't work and should be fixed.
> * int a = fgetc(fp);
> * int b = fgetc(fp);
> * unsigned int ux = (((unsigned)b) <<
| a;
>[...]
> * int x;
> * if (ux >= 0x8000u) {
> * * * x = 0xffffu - ux;
> * * * x = -x - 1;
> * }
> * else x = ux; /* conversion is in range possible */
Ok, it could be a solution. Another solution would be (if I assume the
presence of int16_t):
int i = (int16_t)(((unsigned)b) <<

| a;
> This came up here some time ago (July 2010) and Tim Rentsch came up
> with:
>
> * (int)(ux & 32767) - (int)(ux/2 & 16384) - (int)(ux/2 & 16384);
>
> which has several advantages over my suggestion.
I found the _very long_ thread. I'll try to understand it alone, but
it seems difficult for my small knowledge of C language.