By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,042 Members | 1,036 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,042 IT Pros & Developers. It's quick & easy.

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

P: n/a
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.

Oct 26 '07 #1
Share this Question
Share on Google+
23 Replies


P: n/a
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

Oct 26 '07 #2

P: n/a
On Oct 26, 5:58 pm, CBFalconer <cbfalco...@yahoo.comwrote:
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.

Oct 26 '07 #3

P: n/a
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
Oct 26 '07 #4

P: n/a
On Oct 26, 8:46 pm, pete <pfil...@mindspring.comwrote:
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?

Oct 26 '07 #5

P: n/a
Jorge Peixoto wrote:
>
On Oct 26, 8:46 pm, pete <pfil...@mindspring.comwrote:
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
Oct 26 '07 #6

P: n/a
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
Oct 26 '07 #7

P: n/a
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.

Oct 27 '07 #8

P: n/a
On Fri, 26 Oct 2007 14:17:56 -0700, Jorge Peixoto
<Jo****************@gmail.comwrote:
>On Oct 26, 5:58 pm, CBFalconer <cbfalco...@yahoo.comwrote:
>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
reads 8-bit characters").

--
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/

Oct 27 '07 #9

P: n/a
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

Oct 27 '07 #10

P: n/a
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
Oct 27 '07 #11

P: n/a
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.
Oct 27 '07 #12

P: n/a
* 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.

Oct 27 '07 #13

P: n/a
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.
Oct 27 '07 #14

P: n/a
On Oct 26, 4:44 pm, pete <pfil...@mindspring.comwrote:
Jorge Peixoto wrote:
On Oct 26, 8:46 pm, pete <pfil...@mindspring.comwrote:
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 ?

Oct 27 '07 #15

P: n/a
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.
So the code here *is* redundant! This call
putc((unsigned)((s.i32 >24) & 0xff), fp);

is equivalent to this

putc((unsigned)(s.i32 >24), fp);

In the second call, you cast to unsigned char, which means taking the
remainder modulo 256.
In the first call, you perform bitwise and with 0xff; you are telling
me that this will behave (for unsigned numbers, and this one is
unsigned) as if the number was represented in two's complement; so
this is equivalent to taking the remainder modulo 256.

And I think that even the cast to unsigned is unneeded. Can you get
different results from casting an integer to unsigned, then to
unsigned char, instead of directly casting from integer to unsigned
char?

Oct 27 '07 #16

P: n/a
On Oct 27, 4:03 pm, Jorge Peixoto <JorgePeixotoMor...@gmail.com>
wrote:
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.

So the code here *is* redundant! This call
putc((unsigned)((s.i32 >24) & 0xff), fp);

is equivalent to this

putc((unsigned)(s.i32 >24), fp);

In the second call, you cast to unsigned char, which means taking the
remainder modulo 256.
In the first call, you perform bitwise and with 0xff; you are telling
me that this will behave (for unsigned numbers, and this one is
unsigned) as if the number was represented in two's complement; so
this is equivalent to taking the remainder modulo 256.
Oh wait, he casts to unsigned *after* the and.

In any event, that FAQ answer needs clarification !
Oct 27 '07 #17

P: n/a
"James Kuyper" <ja*********@verizon.neta écrit dans le message de news:
dgIUi.3555$eD3.688@trnddc03...
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.
BCD representations would be problematic for integer types, but not for
floating point where they actually have interesting properties, especially
for financial and accounting applications.

--
Chqrlie.
Oct 27 '07 #18

P: n/a
"James Kuyper" <ja*********@verizon.neta écrit dans le message de news:
IUEUi.94$a01.65@trnddc06...
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.
That's the beauty of this code, it does not even assume char to be eight bit
wide. It is not fully portable to weird obsolete non 2's complement
architectures, but it does produce 4 octets on the stream even if CHAR_BIT
!= 8.

If CHAR_BIT == 8, the mask is not necessary.

--
Chqrlie.
Oct 27 '07 #19

P: n/a
Chad wrote:
>
On Oct 26, 4:44 pm, pete <pfil...@mindspring.comwrote:
There are three allowable ways to represent (-1) in 16 bits:
1111 1111 1111 1111
1111 1111 1111 1110
1000 0000 0000 0001
Would 0xff on a 16 bit machine be represented as
0000 0000 1111 1111
In the manner of notation that I was using above, yes.

--
pete
Oct 28 '07 #20

P: n/a
Jorge Peixoto wrote:
>
>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.

So the code here *is* redundant! This call
putc((unsigned)((s.i32 >24) & 0xff), fp);
is equivalent to this
putc((unsigned)(s.i32 >24), fp);
No it isn't. What if a byte (or char) is larger than 8 bits?

--
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

Oct 28 '07 #21

P: n/a
On Fri, 26 Oct 2007 12:30:16 -0700, 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.
Well, suppose you have a 9-bit machine and you want to write a
file in a 8-bit format. The most reasonable thing to do is not to
use the most significant bit in each byte, i.e. only using bytes
from 0000 to 0377. Now, suppose that you must read from such a
file. You could simply assume that the most significant bit is
never set, but could also discard it anyway, simply ignoring it.
This way the code wouldn't break if, er..., alpha particles set
the most significant bit of a byte.
--
Army1987 (Replace "NOSPAM" with "email")
A hamburger is better than nothing.
Nothing is better than eternal happiness.
Therefore, a hamburger is better than eternal happiness.

Oct 28 '07 #22

P: n/a
On Sat, 27 Oct 2007 20:41:59 +0200, Charlie Gordon wrote:
"James Kuyper" <ja*********@verizon.neta écrit dans le message de news:
dgIUi.3555$eD3.688@trnddc03...
>Jorge Peixoto wrote:
>>So a machine that uses BCD would have to do emulation to be the target
of a C implementation?
Yes. [...]
BCD representations would be problematic for integer types, but not for
floating point where they actually have interesting properties, especially
for financial and accounting applications.
Indeed, the standard doesn't require FLT_RADIX to be a power of 2.
--
Army1987 (Replace "NOSPAM" with "email")
A hamburger is better than nothing.
Nothing is better than eternal happiness.
Therefore, a hamburger is better than eternal happiness.

Oct 28 '07 #23

P: n/a
On Oct 28, 1:10 pm, CBFalconer <cbfalco...@yahoo.comwrote:
Jorge Peixoto wrote:
So the code here *is* redundant! This call
putc((unsigned)((s.i32 >24) & 0xff), fp);
is equivalent to this
putc((unsigned)(s.i32 >24), fp);

No it isn't. What if a byte (or char) is larger than 8 bits?
The OP stipulated that this code is written with
the assumption of char being 8 bits.

Oct 28 '07 #24

This discussion thread is closed

Replies have been disabled for this discussion.