Why write putc(s.i16 & 0xff, fp);

Discussion in 'C Programming' started by Jorge Peixoto, Oct 26, 2007.

1. Jorge PeixotoGuest

In the answer to question 12.42 of the C FAQ, we have this code:

putc((unsigned)((s.i32 >> 24) & 0xff), fp);
putc((unsigned)((s.i32 >> 16) & 0xff), fp);
putc((unsigned)((s.i32 >> 8) & 0xff), fp);
putc((unsigned)(s.i32 & 0xff), fp);

putc((s.i16 >> 8) & 0xff, fp);
putc(s.i16 & 0xff, fp);

Why the & 0xff ? The putc function casts its argument to an unsigned
char, so anything but the 8 lower bits is automatically discarded. And
the code already assumes the a char is 8 bits.

Jorge Peixoto, Oct 26, 2007

2. CBFalconerGuest

Jorge Peixoto wrote:
>
> In the answer to question 12.42 of the C FAQ, we have this code:
>
> putc((unsigned)((s.i32 >> 24) & 0xff), fp);
> putc((unsigned)((s.i32 >> 16) & 0xff), fp);
> putc((unsigned)((s.i32 >> 8) & 0xff), fp);
> putc((unsigned)(s.i32 & 0xff), fp);
>
> putc((s.i16 >> 8) & 0xff, fp);
> putc(s.i16 & 0xff, fp);
>
> Why the & 0xff ? The putc function casts its argument to an unsigned
> char, so anything but the 8 lower bits is automatically discarded. And
> the code already assumes the a char is 8 bits.

Where did you get the magic number 8 there? Bytes and chars can be
any size greater or equal to 8, given by CHAR_BIT in limits.h.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

CBFalconer, Oct 26, 2007

3. Jorge PeixotoGuest

On Oct 26, 5:58 pm, CBFalconer <> wrote:
> Jorge Peixoto wrote:
>
> > In the answer to question 12.42 of the C FAQ, we have this code:

>
> > putc((unsigned)((s.i32 >> 24) & 0xff), fp);
> > putc((unsigned)((s.i32 >> 16) & 0xff), fp);
> > putc((unsigned)((s.i32 >> 8) & 0xff), fp);
> > putc((unsigned)(s.i32 & 0xff), fp);

>
> > putc((s.i16 >> 8) & 0xff, fp);
> > putc(s.i16 & 0xff, fp);

>
> > Why the & 0xff ? The putc function casts its argument to an unsigned
> > char, so anything but the 8 lower bits is automatically discarded. And
> > the code already assumes the a char is 8 bits.

>
> Where did you get the magic number 8 there? Bytes and chars can be
> any size greater or equal to 8, given by CHAR_BIT in limits.h

Yes, but this code (which is from the C FAQ) already assumes that char
is 8 bits. Read the answer to the question 12.42 of the FAQ.

Jorge Peixoto, Oct 26, 2007
4. peteGuest

Jorge Peixoto wrote:
>
> In the answer to question 12.42 of the C FAQ, we have this code:
>
> putc((unsigned)((s.i32 >> 24) & 0xff), fp);
> putc((unsigned)((s.i32 >> 16) & 0xff), fp);
> putc((unsigned)((s.i32 >> 8) & 0xff), fp);
> putc((unsigned)(s.i32 & 0xff), fp);
>
> putc((s.i16 >> 8) & 0xff, fp);
> putc(s.i16 & 0xff, fp);
>
> Why the & 0xff ? The putc function casts its argument to an unsigned
> char, so anything but the 8 lower bits is automatically discarded. And
> the code already assumes the a char is 8 bits.

If the representation of negative integers isn't two's complement,
then converting to unsigned char
is different from discarding bits when s.i16 is negative.

--
pete

pete, Oct 26, 2007
5. Jorge PeixotoGuest

On Oct 26, 8:46 pm, pete <> wrote:
> Jorge Peixoto wrote:
>
> > In the answer to question 12.42 of the C FAQ, we have this code:

>
> > putc((unsigned)((s.i32 >> 24) & 0xff), fp);
> > putc((unsigned)((s.i32 >> 16) & 0xff), fp);
> > putc((unsigned)((s.i32 >> 8) & 0xff), fp);
> > putc((unsigned)(s.i32 & 0xff), fp);

>
> > putc((s.i16 >> 8) & 0xff, fp);
> > putc(s.i16 & 0xff, fp);

>
> > Why the & 0xff ? The putc function casts its argument to an unsigned
> > char, so anything but the 8 lower bits is automatically discarded. And
> > the code already assumes the a char is 8 bits.

>
> If the representation of negative integers isn't two's complement,
> then converting to unsigned char
> is different from discarding bits when s.i16 is negative.
>
> --
> pete

It doesn't matter.

The standard guarantees (according to http://c-faq.com/decl/inttypes.html)
that an unsigned char can hold any integer from 0 to 255. Since we are
already assuming that char is 8 bits, it can hold at most 256 numbers;
there are already 256 numbers between 0 and 255, so 0-255 is exactly
the range of numbers that an unsigned char can hold.

As far as I know (if I am wrong here please correct me), when you
convert from an integer to an unsigned, shorter one, the result is the
nonnegative remander in the division by a number that is 1 bigger
than the maximum number that can be represented by the smaller type.
In our case, this number is 256.

Taking the remainder modulo 256 is equivalent to bitwise and with
0xff, isn't it?

Jorge Peixoto, Oct 27, 2007
6. peteGuest

Jorge Peixoto wrote:
>
> On Oct 26, 8:46 pm, pete <> wrote:
> > Jorge Peixoto wrote:
> >
> > > In the answer to question 12.42 of the C FAQ, we have this code:

> >
> > > putc((unsigned)((s.i32 >> 24) & 0xff), fp);
> > > putc((unsigned)((s.i32 >> 16) & 0xff), fp);
> > > putc((unsigned)((s.i32 >> 8) & 0xff), fp);
> > > putc((unsigned)(s.i32 & 0xff), fp);

> >
> > > putc((s.i16 >> 8) & 0xff, fp);
> > > putc(s.i16 & 0xff, fp);

> >
> > > Why the & 0xff ? The putc function casts its argument to an unsigned
> > > char, so anything but the 8 lower bits is automatically discarded. And
> > > the code already assumes the a char is 8 bits.

> >
> > If the representation of negative integers isn't two's complement,
> > then converting to unsigned char
> > is different from discarding bits when s.i16 is negative.
> >
> > --
> > pete

>
> It doesn't matter.
>
> The standard guarantees (according to http://c-faq.com/decl/inttypes.html)
> that an unsigned char can hold any integer from 0 to 255. Since we are
> already assuming that char is 8 bits, it can hold at most 256 numbers;
> there are already 256 numbers between 0 and 255, so 0-255 is exactly
> the range of numbers that an unsigned char can hold.
>
> As far as I know (if I am wrong here please correct me), when you
> convert from an integer to an unsigned, shorter one, the result is the
> nonnegative remander in the division by a number that is 1 bigger
> than the maximum number that can be represented by the smaller type.
> In our case, this number is 256.
> Taking the remainder modulo 256 is equivalent to bitwise and with
> 0xff, isn't it?

No.

There are three allowable ways to represent (-1) in 16 bits:
1111 1111 1111 1111
1111 1111 1111 1110
1000 0000 0000 0001

If s.i16 has a value of (-1),
then (s.i16 & 0xff) can have a value of either
255, or 254, or 1.

((unsigned char)-1) is always equal to UCHAR_MAX.

--
pete

pete, Oct 27, 2007
7. peteGuest

CBFalconer wrote:
>
> Jorge Peixoto wrote:
> >
> > In the answer to question 12.42 of the C FAQ, we have this code:
> >
> > putc((unsigned)((s.i32 >> 24) & 0xff), fp);
> > putc((unsigned)((s.i32 >> 16) & 0xff), fp);
> > putc((unsigned)((s.i32 >> 8) & 0xff), fp);
> > putc((unsigned)(s.i32 & 0xff), fp);
> >
> > putc((s.i16 >> 8) & 0xff, fp);
> > putc(s.i16 & 0xff, fp);
> >
> > Why the & 0xff ?
> > The putc function casts its argument to an unsigned char,
> > so anything but the 8 lower bits is automatically discarded.
> > And the code already assumes the a char is 8 bits.

>
> Where did you get the magic number 8 there?

It says so, here: http://c-faq.com/stdio/extconform.html

--
pete

pete, Oct 27, 2007
8. CBFalconerGuest

Jorge Peixoto wrote:
> pete <> wrote:
>> Jorge Peixoto wrote:
>>
>>> In the answer to question 12.42 of the C FAQ, we have this code:

>>
>>> putc((unsigned)((s.i32 >> 24) & 0xff), fp);
>>> putc((unsigned)((s.i32 >> 16) & 0xff), fp);
>>> putc((unsigned)((s.i32 >> 8) & 0xff), fp);
>>> putc((unsigned)(s.i32 & 0xff), fp);
>>> putc((s.i16 >> 8) & 0xff, fp);
>>> putc(s.i16 & 0xff, fp);

>>
>>> Why the & 0xff ? The putc function casts its argument to an
>>> unsigned char, so anything but the 8 lower bits is automatically
>>> discarded. And the code already assumes the a char is 8 bits.

>>
>> If the representation of negative integers isn't two's complement,
>> then converting to unsigned char is different from discarding bits
>> when s.i16 is negative.

>
> It doesn't matter.
>
> The standard guarantees (according to http://c-faq.com/decl/inttypes.html)
> that an unsigned char can hold any integer from 0 to 255. Since we
> are already assuming that char is 8 bits, it can hold at most 256
> numbers; there are already 256 numbers between 0 and 255, so 0-255
> is exactly the range of numbers that an unsigned char can hold.

IMO the fact that the FAQ makes (and documents) assumptions about
CHAR_BIT is no excuse for doing the same in this newsgroup,
especially without clearly so documenting. In other words, it does
matter, and omitting it will lead all sorts of innocent newbies
into dingy dark despondent passages. Look with especial suspicion
on any constant '8' in your code.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

CBFalconer, Oct 27, 2007
9. Jorge PeixotoGuest

> If s.i16 has a value of (-1),
> then (s.i16 & 0xff) can have a value of either
> 255, or 254, or 1.
>
> ((unsigned char)-1) is always equal to UCHAR_MAX.
>
> --
> pete

I didn't know that. So the bitwise operators are machine-dependent?
Are you telling me that the following simple code

#include <stdio.h>

int main (void) {
unsigned t = 256;
t &= 0xff;
printf ("%u\n", t);
return 0;
}

is machine dependent*? I thought that the bitwise operators would
behave as if the number is in two's complement, in any machine. It is
amazing if the simple code above is machine dependent.

* Even positive numbers may be represented in a crazy way. On the
Deathstation, positive numbers are represented in base 1, that is, the
number is the number of 1s in the variable. So 0 is all bits 0, 1 is
1, two is 11, three is 111, etc.

Jorge Peixoto, Oct 27, 2007
10. James KuyperGuest

Jorge Peixoto wrote:
....
> I didn't know that. So the bitwise operators are machine-dependent?

There are three permitted representations for negative values of signed
integer types; which one is actually used is implementation-defined.

The binary | and & operators are defined by the standard only in terms
of their operations on value and sign bits; the consequences of that
definition when applied to signed types are therefore tied to which of
those three representations is used for negative values.

> Are you telling me that the following simple code
>
> #include <stdio.h>
>
> int main (void) {
> unsigned t = 256;
> t &= 0xff;
> printf ("%u\n", t);
> return 0;
> }
>
> is machine dependent*?

No. You'd have to use a signed type with a negative value in order to
get behavior that is implementation-defined.

James Kuyper, Oct 27, 2007
11. jaysomeGuest

On Fri, 26 Oct 2007 14:17:56 -0700, Jorge Peixoto
<> wrote:

>On Oct 26, 5:58 pm, CBFalconer <> wrote:
>> Jorge Peixoto wrote:
>>
>> > In the answer to question 12.42 of the C FAQ, we have this code:

>>
>> > putc((unsigned)((s.i32 >> 24) & 0xff), fp);
>> > putc((unsigned)((s.i32 >> 16) & 0xff), fp);
>> > putc((unsigned)((s.i32 >> 8) & 0xff), fp);
>> > putc((unsigned)(s.i32 & 0xff), fp);

>>
>> > putc((s.i16 >> 8) & 0xff, fp);
>> > putc(s.i16 & 0xff, fp);

>>
>> > Why the & 0xff ? The putc function casts its argument to an unsigned
>> > char, so anything but the 8 lower bits is automatically discarded. And
>> > the code already assumes the a char is 8 bits.

>>
>> Where did you get the magic number 8 there? Bytes and chars can be
>> any size greater or equal to 8, given by CHAR_BIT in limits.h

>
>Yes, but this code (which is from the C FAQ) already assumes that char
>is 8 bits. Read the answer to the question 12.42 of the FAQ.

Indeed. And the FAQ explicitly says so ("This code assumes that getc

--
jay

http://c-faq.com/
http://msdn2.microsoft.com/en-us/express/default.aspx
http://www.gimpel.com/
http://www.ubuntu.com/
http://www.embedded.com/

jaysome, Oct 27, 2007
12. CBFalconerGuest

Jorge Peixoto wrote:
>

.... snip ...
>
> * Even positive numbers may be represented in a crazy way. On the
> Deathstation, positive numbers are represented in base 1, that is,
> the number is the number of 1s in the variable. So 0 is all bits
> 0, 1 is 1, two is 11, three is 111, etc.

Not so. The fundamental binary representation of positive integers
is specified in the standard.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

CBFalconer, Oct 27, 2007
13. WillemGuest

Jorge wrote:
) In the answer to question 12.42 of the C FAQ, we have this code:
)
) putc((unsigned)((s.i32 >> 24) & 0xff), fp);
) putc((unsigned)((s.i32 >> 16) & 0xff), fp);
) putc((unsigned)((s.i32 >> 8) & 0xff), fp);
) putc((unsigned)(s.i32 & 0xff), fp);
)
)
) putc((s.i16 >> 8) & 0xff, fp);
) putc(s.i16 & 0xff, fp);
)
) Why the & 0xff ? The putc function casts its argument to an unsigned
) char, so anything but the 8 lower bits is automatically discarded. And
) the code already assumes the a char is 8 bits.

Think about what would happen with this bit of code on a system where
a char is 9 bits. What would the result be ? What exactly would putc
be outputting ?

SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT

Willem, Oct 27, 2007
14. James KuyperGuest

Willem wrote:
> Jorge wrote:
> ) In the answer to question 12.42 of the C FAQ, we have this code:
> )
> ) putc((unsigned)((s.i32 >> 24) & 0xff), fp);
> ) putc((unsigned)((s.i32 >> 16) & 0xff), fp);
> ) putc((unsigned)((s.i32 >> 8) & 0xff), fp);
> ) putc((unsigned)(s.i32 & 0xff), fp);
> )
> )
> ) putc((s.i16 >> 8) & 0xff, fp);
> ) putc(s.i16 & 0xff, fp);
> )
> ) Why the & 0xff ? The putc function casts its argument to an unsigned
> ) char, so anything but the 8 lower bits is automatically discarded. And
> ) the code already assumes the a char is 8 bits.
>
> Think about what would happen with this bit of code on a system where
> a char is 9 bits. What would the result be ? What exactly would putc
> be outputting ?

That char should be assumed to be 8 bits is part of the design
specifications for this code, so that can't be the justification for the
&0xff.

James Kuyper, Oct 27, 2007
15. Charlie GordonGuest

"CBFalconer" <> a écrit dans le message de news:
...
> Jorge Peixoto wrote:
>> pete <> wrote:
>>> Jorge Peixoto wrote:
>>>
>>>> In the answer to question 12.42 of the C FAQ, we have this code:
>>>
>>>> putc((unsigned)((s.i32 >> 24) & 0xff), fp);
>>>> putc((unsigned)((s.i32 >> 16) & 0xff), fp);
>>>> putc((unsigned)((s.i32 >> 8) & 0xff), fp);
>>>> putc((unsigned)(s.i32 & 0xff), fp);
>>>> putc((s.i16 >> 8) & 0xff, fp);
>>>> putc(s.i16 & 0xff, fp);
>>>
>>>> Why the & 0xff ? The putc function casts its argument to an
>>>> unsigned char, so anything but the 8 lower bits is automatically
>>>> discarded. And the code already assumes the a char is 8 bits.
>>>
>>> If the representation of negative integers isn't two's complement,
>>> then converting to unsigned char is different from discarding bits
>>> when s.i16 is negative.

>>
>> It doesn't matter.
>>
>> The standard guarantees (according to
>> http://c-faq.com/decl/inttypes.html)
>> that an unsigned char can hold any integer from 0 to 255. Since we
>> are already assuming that char is 8 bits, it can hold at most 256
>> numbers; there are already 256 numbers between 0 and 255, so 0-255
>> is exactly the range of numbers that an unsigned char can hold.

>
> IMO the fact that the FAQ makes (and documents) assumptions about
> CHAR_BIT is no excuse for doing the same in this newsgroup,
> especially without clearly so documenting. In other words, it does
> matter, and omitting it will lead all sorts of innocent newbies
> into dingy dark despondent passages. Look with especial suspicion
> on any constant '8' in your code.

You are being excessively picky here: the OP writes "the code already
assumes the char is 8 bits". Innocent newbies should be shielded from these
arcane considerations until they become proficient enough to master them,
and versatile enough to actually care about them. Bashing beginners with
the intricacies of non twos-complement representations is stupid and
counter-productive. What would you think of a school teacher that would
concentrate on esoteric typographical details and abtruse considerations on
her pupils ?

These constant recriminations are just a form of pedantry, far too common on
this newsgroup, stretched to the extreme in a form a pointless sickening
competition.

--
Chqrlie

Charlie Gordon, Oct 27, 2007
16. Jorge PeixotoGuest

> > * Even positive numbers may be represented in a crazy way. On the
> > Deathstation, positive numbers are represented in base 1, that is,
> > the number is the number of 1s in the variable. So 0 is all bits
> > 0, 1 is 1, two is 11, three is 111, etc.

>
> Not so. The fundamental binary representation of positive integers
> is specified in the standard.

So a machine that uses BCD would have to do emulation to be the target
of a C implementation?

In any event, I think this issue should be in the answer to the
question. People will be thinking why is that &0xff needed, and the
FAQ should be didactic.

Jorge Peixoto, Oct 27, 2007
17. Charlie GordonGuest

"pete" <> a écrit dans le message de news:
...
> Jorge Peixoto wrote:
>>
>> On Oct 26, 8:46 pm, pete <> wrote:
>> > Jorge Peixoto wrote:
>> >
>> > > In the answer to question 12.42 of the C FAQ, we have this code:
>> >
>> > > putc((unsigned)((s.i32 >> 24) & 0xff), fp);
>> > > putc((unsigned)((s.i32 >> 16) & 0xff), fp);
>> > > putc((unsigned)((s.i32 >> 8) & 0xff), fp);
>> > > putc((unsigned)(s.i32 & 0xff), fp);
>> >
>> > > putc((s.i16 >> 8) & 0xff, fp);
>> > > putc(s.i16 & 0xff, fp);
>> >
>> > > Why the & 0xff ? The putc function casts its argument to an unsigned
>> > > char, so anything but the 8 lower bits is automatically discarded.
>> > > And
>> > > the code already assumes the a char is 8 bits.
>> >
>> > If the representation of negative integers isn't two's complement,
>> > then converting to unsigned char
>> > is different from discarding bits when s.i16 is negative.
>> >
>> > --
>> > pete

>>
>> It doesn't matter.
>>
>> The standard guarantees (according to
>> http://c-faq.com/decl/inttypes.html)
>> that an unsigned char can hold any integer from 0 to 255. Since we are
>> already assuming that char is 8 bits, it can hold at most 256 numbers;
>> there are already 256 numbers between 0 and 255, so 0-255 is exactly
>> the range of numbers that an unsigned char can hold.
>>
>> As far as I know (if I am wrong here please correct me), when you
>> convert from an integer to an unsigned, shorter one, the result is the
>> nonnegative remander in the division by a number that is 1 bigger
>> than the maximum number that can be represented by the smaller type.
>> In our case, this number is 256.
>> Taking the remainder modulo 256 is equivalent to bitwise and with
>> 0xff, isn't it?

>
> No.
>
> There are three allowable ways to represent (-1) in 16 bits:
> 1111 1111 1111 1111
> 1111 1111 1111 1110
> 1000 0000 0000 0001
>
> If s.i16 has a value of (-1),
> then (s.i16 & 0xff) can have a value of either
> 255, or 254, or 1.
>
> ((unsigned char)-1) is always equal to UCHAR_MAX.

The OP's purpose is to serialize the integer to a stream. For maximum
portability, it is obviously be preferable that the resulting stream be
independant of the particular representation of integers on the stream
writer and reader. Therefore the method used is inappropriate, s.i32 should
first be converted to an unsigned type, and then shifted around and masked
off in chunks of fixed numbers of bits (8 is an obvious choice), streamed
out in a defined order (big endian here).

putc(((unsigned long)s.i32 >> 24) & 0xff, fp);
putc(((unsigned long)s.i32 >> 16) & 0xff, fp);
putc(((unsigned long)s.i32 >> 8) & 0xff, fp);
putc(((unsigned long)s.i32 >> 0) & 0xff, fp);

putc(((unsigned int)s.i16 >> 8) & 0xff, fp);
putc(((unsigned int)s.i16 >> 0) & 0xff, fp);

This code can be simplified, extra operations are here for reasons of
symmetry.

--
Chqrlie.

Charlie Gordon, Oct 27, 2007
18. James KuyperGuest

Jorge Peixoto wrote:
....
> So a machine that uses BCD would have to do emulation to be the target
> of a C implementation?

Yes. Bitwise operators must be implemented as if operating on a binary
representation of the value, which would presumably not be a simple
operation on such a machine. Trinary machines (which have some
interesting advantages in certain contexts compared to binary machines)
would also be problematic.

James Kuyper, Oct 27, 2007
19. CBFalconerGuest

Charlie Gordon wrote:
> "CBFalconer" <> a écrit:
>

.... snip ...
>
>> IMO the fact that the FAQ makes (and documents) assumptions about
>> CHAR_BIT is no excuse for doing the same in this newsgroup,
>> especially without clearly so documenting. In other words, it does
>> matter, and omitting it will lead all sorts of innocent newbies
>> into dingy dark despondent passages. Look with especial suspicion
>> on any constant '8' in your code.

>
> You are being excessively picky here: the OP writes "the code
> already assumes the char is 8 bits". Innocent newbies should be
> shielded from these arcane considerations until they become
> proficient enough to master them, and versatile enough to
> actually care about them. Bashing beginners with the intricacies
> of non twos-complement representations is stupid and counter-
> productive. What would you think of a school teacher that would
> concentrate on esoteric typographical details and abtruse
> considerations on ancient hieroglyphs instead of first polishing
> the basic reading skills of her pupils ?
>
> These constant recriminations are just a form of pedantry, far too
> common on this newsgroup, stretched to the extreme in a form a
> pointless sickening competition.

You mistake the criticism. It is not about 1's vs 2's complement
vs sign-magnitude (which is easily handled by dealing with values,
rather than bit pattern), but about the size of CHAR_BIT,
specifying the size of a byte on that machine.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

CBFalconer, Oct 27, 2007

On Oct 26, 4:44 pm, pete <> wrote:
> Jorge Peixoto wrote:
>
> > On Oct 26, 8:46 pm, pete <> wrote:
> > > Jorge Peixoto wrote:

>
> > > > In the answer to question 12.42 of the C FAQ, we have this code:

>
> > > > putc((unsigned)((s.i32 >> 24) & 0xff), fp);
> > > > putc((unsigned)((s.i32 >> 16) & 0xff), fp);
> > > > putc((unsigned)((s.i32 >> 8) & 0xff), fp);
> > > > putc((unsigned)(s.i32 & 0xff), fp);

>
> > > > putc((s.i16 >> 8) & 0xff, fp);
> > > > putc(s.i16 & 0xff, fp);

>
> > > > Why the & 0xff ? The putc function casts its argument to an unsigned
> > > > char, so anything but the 8 lower bits is automatically discarded. And
> > > > the code already assumes the a char is 8 bits.

>
> > > If the representation of negative integers isn't two's complement,
> > > then converting to unsigned char
> > > is different from discarding bits when s.i16 is negative.

>
> > > --
> > > pete

>
> > It doesn't matter.

>
> > The standard guarantees (according tohttp://c-faq.com/decl/inttypes.html)
> > that an unsigned char can hold any integer from 0 to 255. Since we are
> > already assuming that char is 8 bits, it can hold at most 256 numbers;
> > there are already 256 numbers between 0 and 255, so 0-255 is exactly
> > the range of numbers that an unsigned char can hold.

>
> > As far as I know (if I am wrong here please correct me), when you
> > convert from an integer to an unsigned, shorter one, the result is the
> > nonnegative remander in the division by a number that is 1 bigger
> > than the maximum number that can be represented by the smaller type.
> > In our case, this number is 256.
> > Taking the remainder modulo 256 is equivalent to bitwise and with
> > 0xff, isn't it?

>
> No.
>
> There are three allowable ways to represent (-1) in 16 bits:
> 1111 1111 1111 1111
> 1111 1111 1111 1110
> 1000 0000 0000 0001
>
> If s.i16 has a value of (-1),
> then (s.i16 & 0xff) can have a value of either
> 255, or 254, or 1.
>
> ((unsigned char)-1) is always equal to UCHAR_MAX.
>
> --
> pete

Would 0xff on a 16 bit machine be represented as
0000 0000 1111 1111

In other words, would there be leading zero's before 1111 1111 ?