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

Bit mask

P: n/a
Als
What's an efficient way to mask a last 3 bits of a 8-bit char and make them
all zero?

Bit-shifting is possible but not sure if it is efficient enough.

Example:

01011[010] --> 01011[000]

Thanks!
Nov 14 '05 #1
Share this Question
Share on Google+
24 Replies


P: n/a
Als <no****@nowhere.net> scribbled the following:
What's an efficient way to mask a last 3 bits of a 8-bit char and make them
all zero? Bit-shifting is possible but not sure if it is efficient enough. Example: 01011[010] --> 01011[000] Thanks!


Well, a really simple way would be ANDing with ~7.
For example:
unsigned char x = 0x5A; /* the same as binary 01011010 */
x = x & ~7; /* clear last 3 bits */
Is it efficient? It depends on your implementation.

--
/-- Joona Palaste (pa*****@cc.helsinki.fi) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"C++ looks like line noise."
- Fred L. Baube III
Nov 14 '05 #2

P: n/a
Mark A. Odell wrote:
Joona I Palaste <pa*****@cc.helsinki.fi> wrote in
news:bt**********@oravannahka.helsinki.fi:
unsigned char x = 0x5A;

x &= (unsigned char) ~0x07;


It's practically the same thing, and whatever efficiency difference
there would be will probably get lost in compiler optimisation. I just
thought my version was clearer to read. Suit yourself.

I meant nothing WRT efficiency, just that I thought that &= is the more
common idiom and that you needed to cast ~0x07 to unsigned char.


Why would the cast be needed? It seems useless to me, since the result
will be promoted back to int (probably - unsigned int is theoretically
possible also) anyway.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #3

P: n/a
Als
Eric Sosman <Er*********@sun.com> wrote in message
news:3F***************@sun.com...
Als wrote:

What's an efficient way to mask a last 3 bits of a 8-bit char and make them all zero?

Bit-shifting is possible but not sure if it is efficient enough.

Example:

01011[010] --> 01011[000]


Many or perhaps even most C implementations use an
eight-bit `char', but that is not actually guaranteed
by the language, and implementations using wider `char'
are known to exist. Still:

unsigned char byte = 0x5A; /* 00...01011010 */


Is there any reason that you use "unsigned char" instead of "char" above?
Thanks!
Nov 14 '05 #4

P: n/a
Als wrote:

Eric Sosman <Er*********@sun.com> wrote in message
news:3F***************@sun.com...
Als wrote:

What's an efficient way to mask a last 3 bits of a 8-bit char and make them all zero?

Bit-shifting is possible but not sure if it is efficient enough.

Example:

01011[010] --> 01011[000]


Many or perhaps even most C implementations use an
eight-bit `char', but that is not actually guaranteed
by the language, and implementations using wider `char'
are known to exist. Still:

unsigned char byte = 0x5A; /* 00...01011010 */


Is there any reason that you use "unsigned char"
instead of "char" above?


The result of bitwise operations are implementation defined
of the sign bit is set prior to or during the operation.

--
pete
Nov 14 '05 #5

P: n/a
On 7 Jan 2004 18:33:24 GMT, "Mark A. Odell" <no****@embeddedfw.com>
wrote in comp.lang.c:
Joona I Palaste <pa*****@cc.helsinki.fi> wrote in
news:bt**********@oravannahka.helsinki.fi:
Example:

01011[010] --> 01011[000]

Thanks!


Well, a really simple way would be ANDing with ~7.
For example:
unsigned char x = 0x5A; /* the same as binary 01011010 */
x = x & ~7; /* clear last 3 bits */
Is it efficient? It depends on your implementation.


Why not do:

unsigned char x = 0x5A;

x &= (unsigned char) ~0x07;

--
- Mark ->


No gain, really. x will be promoted to either int or unsigned int,
and the numeric literal 0x5A, which has type int, will either be
unchanged or also promoted to unsigned int, before binary operation is
performed. Then the result will be converted back to unsigned char
for assignment back into x.

So casting the constant to unsigned char merely adds noise to the
source without changing a thing. If the constant were large enough
that it might actually be negative, a cast to (unsigned) could be
beneficial.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #6

P: n/a


Eric wrote:
Als <no****@nowhere.net> wrote:

What's an efficient way to mask a last 3 bits of a 8-bit char and make them
all zero?

unsigned char x = 90;

x = x & ~7;


I'm curious about using the ~ operator. Will the compiler recognise ~7
as a constant value, or will the compiled code include one's complement
instruction(s)?

Wouldn't this be better:

x &= 0xf8;

For me this is more readable than the above...
Regards,
Anders

Nov 14 '05 #7

P: n/a
Anders Mikkelsen wrote:

Eric wrote:
Als <no****@nowhere.net> wrote:

What's an efficient way to mask a last 3 bits
of a 8-bit char and make them all zero?

unsigned char x = 90;

x = x & ~7;


I'm curious about using the ~ operator. Will the compiler recognise ~7
as a constant value,


It *is* a constant value.
or will the compiled code include one's complement
instruction(s)?
It can do that too, but I would expect that it wouldn't.

Wouldn't this be better:

x &= 0xf8;

For me this is more readable than the above...


That will mask an 8 bit char as OP specified,
but (x &= ~7) will work on a char of any width.

--
pete
Nov 14 '05 #8

P: n/a
Anders Mikkelsen wrote:
I'm curious about using the ~ operator. Will the compiler recognise ~7
as a constant value, or will the compiled code include one's complement
instruction(s)?
Hmm. Very dangerous to predict compiler behaviors - or did you
have a particular compiler in mind? It's a much a constant value
as -7 (which still says nothing about the compiler's behavior)
Wouldn't this be better:

x &= 0xf8;

For me this is more readable than the above...


Perhaps more readable for you; but what if CHAR_BIT isn't less
than nine bits? Imagine that this program is run on my DS9K
configured for 12-bit chars - what then?

--
Morris Dovey
West Des Moines, Iowa USA
C links at http://www.iedu.com/c
Read my lips: The apple doesn't fall far from the tree.

Nov 14 '05 #9

P: n/a
eg*************@verizon.net (Eric) wrote in message news:<1g772zd.1aoukoy5c8ubkN%eg*************@veriz on.net>...
Als <no****@nowhere.net> wrote:
What's an efficient way to mask a last 3 bits of a 8-bit char and make them
all zero?


unsigned char x = 90;

x = x & ~7;


Is there anything wrong with this one ?

x = x & 0xf8;
- Ravi
Nov 14 '05 #10

P: n/a
Ravi Uday <ra*****@yahoo.com> scribbled the following:
eg*************@verizon.net (Eric) wrote in message news:<1g772zd.1aoukoy5c8ubkN%eg*************@veriz on.net>...
Als <no****@nowhere.net> wrote:
> What's an efficient way to mask a last 3 bits of a 8-bit char and make them
> all zero?
unsigned char x = 90;

x = x & ~7;

Is there anything wrong with this one ? x = x & 0xf8;


As the OP specified, no, but Eric's solution works for non-8 bit chars
too.

--
/-- Joona Palaste (pa*****@cc.helsinki.fi) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"The large yellow ships hung in the sky in exactly the same way that bricks
don't."
- Douglas Adams
Nov 14 '05 #11

P: n/a
Jack Klein <ja*******@spamcop.net> wrote in
news:gf********************************@4ax.com:

Why not do:

unsigned char x = 0x5A;

x &= (unsigned char) ~0x07;
No gain, really. x will be promoted to either int or unsigned int,
and the numeric literal 0x5A, which has type int, will either be
unchanged or also promoted to unsigned int, before binary operation is
performed. Then the result will be converted back to unsigned char
for assignment back into x.

So casting the constant to unsigned char merely adds noise to the
source without changing a thing. If the constant were large enough
that it might actually be negative, a cast to (unsigned) could be
beneficial.


I'm so used to 32-bit machines now maybe I'm tainted. Thanks Jack. So I
only need to cast when 'x' or the mask constant exceeds a value
representable signed int?

--
- Mark ->
--
Nov 14 '05 #12

P: n/a
Jack Klein wrote:
unsigned char x = 0x5A;
No gain, really. x will be promoted to either int or unsigned int,
and the numeric literal 0x5A, which has type int, will either be
unchanged or also promoted to unsigned int, before binary operation is
performed. Then the result will be converted back to unsigned char
for assignment back into x.


There's two things wrong with that:
1 The left operand of the assignment operator doesn't get promoted.
2 Constants of type int, are not subject to integer promotions.

N869

6.5.16.1 Simple assignment
Semantics
[#2] In simple assignment (=), the value of the right
operand is converted to the type of the assignment
expression and replaces the value stored in the object
designated by the left operand.

6.5.16 Assignment operators
Semantics
[#3]
The type of an assignment expression is
the type of the left operand unless the left operand has
qualified type, in which case it is the unqualified version
of the type of the left operand.
6.3.1.1 Boolean, characters, and integers
[#2]
If an int can represent all values of the original type, the
value is converted to an int; otherwise, it is converted to
an unsigned int. These are called the integer
promotions.

--
pete
Nov 14 '05 #13

P: n/a
pete wrote:

Jack Klein wrote:
unsigned char x = 0x5A;
No gain, really. x will be promoted to either int or unsigned int,
and the numeric literal 0x5A, which has type int, will either be
unchanged or also promoted to unsigned int,
before binary operation is performed.
Then the result will be converted back to unsigned char
for assignment back into x.
There's two things wrong with that:


unless you were talking about
x &= (unsigned char) ~0x07;


.... which I now realize that you were.
Sorry about that.

--
pete
Nov 14 '05 #14

P: n/a
Eric <eg*************@verizon.net> spoke thus:
x = x & ~7;


Is ~7 guaranteed to be ...11111111111000 on all systems?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #15

P: n/a
Christopher Benson-Manica wrote:

Eric <eg*************@verizon.net> spoke thus:
x = x & ~7;


Is ~7 guaranteed to be ...11111111111000 on all systems?


Yes. There's this pettifogging possibility, though,
that ...1111000 could be a trap representation for `int'
(as far as I know, the only platform for which this is
true is the Deathstation 9000, and then only on alternate
Thursdays when the moon is full). For 100% safety, you
could write `~7u' instead.

... and if that's the worst thing you need to worry
about, you are to be envied.

--
Er*********@sun.com
Nov 14 '05 #16

P: n/a
begin followup to Christopher Benson-Manica:
Is ~7 guaranteed to be ...11111111111000 on all systems?


Well, on a machine running trinary logic ... perhaps using three
charge states of an atom ... where the decimal number '7' is
represented by the digits '21' ... well, how the fuck is bitwise
negation meant to work there?

Perhaps like multiplication with -1, i.e. the zero 'trit' is left
unchanged while the outer two trit values are flipped. In that case
negating '21' results in '12' since leading zeros are not modified.

Yeah.

--
Für Google, Tux und GPL!
Nov 14 '05 #17

P: n/a
Eric Sosman wrote:

Christopher Benson-Manica wrote:

Eric <eg*************@verizon.net> spoke thus:
x = x & ~7;


Is ~7 guaranteed to be ...11111111111000 on all systems?


Yes. There's this pettifogging possibility, though,
that ...1111000 could be a trap representation for `int'
(as far as I know, the only platform for which this is
true is the Deathstation 9000, and then only on alternate
Thursdays when the moon is full). For 100% safety, you
could write `~7u' instead.


I think that's best. As a matter of policy,
I prefer to avoid bitwise operations on signed types,
unless there is a special reason.

--
pete
Nov 14 '05 #18

P: n/a
Eric Sosman <Er*********@sun.com> wrote in message news:<3F***************@sun.com>...
Christopher Benson-Manica wrote:

Eric <eg*************@verizon.net> spoke thus:
x = x & ~7;


Is ~7 guaranteed to be ...11111111111000 on all systems?


Yes. There's this pettifogging possibility, though,
that ...1111000 could be a trap representation for `int'
(as far as I know, the only platform for which this is
true is the Deathstation 9000, and then only on alternate
Thursdays when the moon is full). For 100% safety, you
could write `~7u' instead.


Well, if you think that ~ can change padding bits, then ~7u isn't safe
either, since even unsigned types can have padding, and hence,
potential trap representations (apart from the uintN_t types of
course).

A case to hypothetically consider would be if INT_MIN did not have a
magnitude of 2^N or 2^N-1. In other words, if you consider that an int
can have a bizarre range like (-78269..65318).

--
Peter
Nov 14 '05 #19

P: n/a
Peter Nilsson wrote:

Eric Sosman <Er*********@sun.com> wrote in message news:<3F***************@sun.com>...
Christopher Benson-Manica wrote:

Eric <eg*************@verizon.net> spoke thus:

> x = x & ~7;

Is ~7 guaranteed to be ...11111111111000 on all systems?


Yes. There's this pettifogging possibility, though,
that ...1111000 could be a trap representation for `int'
(as far as I know, the only platform for which this is
true is the Deathstation 9000, and then only on alternate
Thursdays when the moon is full). For 100% safety, you
could write `~7u' instead.


Well, if you think that ~ can change padding bits,
then ~7u isn't safe either, since even unsigned types can have
padding, and hence, potential trap representations
(apart from the uintN_t types of course).


He may have been refering to negative zero, instead of padding bits.

In C99 there's only 3 formats for representing negative integers,
but in C89, the representation for negative integer values
is only specified in broad terms relating to sign and value bits,
which would allow an implementation to define any particular
negative integer value representation, as negative zero.

--
pete
Nov 14 '05 #20

P: n/a
Alexander Bartolich <al*****************@gmx.at> wrote:
begin followup to Christopher Benson-Manica:
Is ~7 guaranteed to be ...11111111111000 on all systems?


Well, on a machine running trinary logic ... perhaps using three
charge states of an atom ... where the decimal number '7' is
represented by the digits '21' ... well, how the fuck is bitwise
negation meant to work there?


Slowly. But it must, because the Standard requires it.

If you ever find a ternary computer with a C compiler, warn me, I could
do with a laugh.

Richard
Nov 14 '05 #21

P: n/a
pete <pf******@mindspring.com> wrote in message news:<3F**********@mindspring.com>...
Peter Nilsson wrote:
Eric Sosman <Er*********@sun.com> wrote in message news:<3F***************@sun.com>...
Christopher Benson-Manica wrote:
>
> Eric <eg*************@verizon.net> spoke thus:
>
> > x = x & ~7;
>
> Is ~7 guaranteed to be ...11111111111000 on all systems?

Yes. There's this pettifogging possibility, though,
that ...1111000 could be a trap representation for `int'
(as far as I know, the only platform for which this is
true is the Deathstation 9000, and then only on alternate
Thursdays when the moon is full). For 100% safety, you
could write `~7u' instead.


Well, if you think that ~ can change padding bits,
then ~7u isn't safe either, since even unsigned types can have
padding, and hence, potential trap representations
(apart from the uintN_t types of course).


He may have been refering to negative zero, instead of padding bits.

In C99 there's only 3 formats for representing negative integers,
but in C89, the representation for negative integer values
is only specified in broad terms relating to sign and value bits,
which would allow an implementation to define any particular
negative integer value representation, as negative zero.


I'm not with you! How is ~7 a negative zero in C89? As I understood
it, there were no trap representations in C89, irrespective of the
representation chosen.

--
Peter
Nov 14 '05 #22

P: n/a
Peter Nilsson wrote:
How is ~7 a negative zero in C89?


The C89 standard does not specify the representation
for the magnitudes of negative integer values.

--
pete
Nov 14 '05 #23

P: n/a
"pete" <pf*****@mindspring.com> wrote in message
news:40***********@mindspring.com...
Peter Nilsson wrote:
How is ~7 a negative zero in C89?


The C89 standard does not specify the representation
for the magnitudes of negative integer values.


But the responses in DR#069, although rather cryptic (both the questions and
responses are rather carelessly mislabled), seems to rule out the
possibility of ~7 being a 'negative zero'.

Given the committee's interpretation of "pure binary numeration system", I'm
not sure what other systems are actually allowed apart from the common 3
(padding bits and 'holes' notwithstanding).

That said, I'm more than happy to stick to the golden rule of not using
signed integers for bit manipulations whenever the sign bit is, or could
become, 1. :-)

--
Peter
Nov 14 '05 #24

P: n/a
Peter Nilsson wrote:

"pete" <pf*****@mindspring.com> wrote in message
news:40***********@mindspring.com...
Peter Nilsson wrote:
How is ~7 a negative zero in C89?
The C89 standard does not specify the representation
for the magnitudes of negative integer values.


But the responses in DR#069,
although rather cryptic (both the questions and
responses are rather carelessly mislabled), seems to rule out the
possibility of ~7 being a 'negative zero'.


I don't see anything there which would prohibit
1111 1111 1111 1000 from representing negative zero.
Given the committee's interpretation of
"pure binary numeration system", I'm
not sure what other systems are actually
allowed apart from the common 3
(padding bits and 'holes' notwithstanding).


The systems which are allowed in C89 are not specified by name,
so any system which uses the sign bit for negative values
followed by any systematic representation of the magnitudes,
would have been valid in C89.

--
pete
Nov 14 '05 #25

This discussion thread is closed

Replies have been disabled for this discussion.