446,406 Members | 888 Online
Need help? Post your question and get tips & solutions from a community of 446,406 IT Pros & Developers. It's quick & easy.

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

 P: n/a Als 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 wrote in news:bt**********@oravannahka.helsinki.fi:unsigned char x = 0x5A;x &= (unsigned char) ~0x07;It's practically the same thing, and whatever efficiency differencethere would be will probably get lost in compiler optimisation. I justthought 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 Eric Sosman 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 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" wrote in comp.lang.c: Joona I Palaste 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 wrote:What's an efficient way to mask a last 3 bits of a 8-bit char and make themall 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 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 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 scribbled the following: eg*************@verizon.net (Eric) wrote in message news:<1g772zd.1aoukoy5c8ubkN%eg*************@veriz on.net>... Als 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 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 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 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 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 wrote in message news:<3F***************@sun.com>... Christopher Benson-Manica wrote: Eric 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 wrote in message news:<3F***************@sun.com>... Christopher Benson-Manica wrote: Eric 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 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 wrote in message news:<3F**********@mindspring.com>... Peter Nilsson wrote: Eric Sosman wrote in message news:<3F***************@sun.com>... Christopher Benson-Manica wrote: > > Eric 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" 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" 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.