Searching \ for '[PIC] C-Compiler: One's complement of unsigned cha' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: techref.massmind.org/techref/microchip/devices.htm?key=pic
Search entire site for: 'C-Compiler: One's complement of unsigned cha'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] C-Compiler: One's complement of unsigned cha'
2005\12\02@043433 by Buehler, Martin

picon face

Why does a one's complement of an 'unsigned char' not return an 'unsigned char'?

example:

unsigned char a,b;

a = 0x03;
b = ~a;                //b = 0xfc

if (a == ~b) {/* true */}
else {/* false */}

according to my understanding, this should always evaluate to 'true', as ´~b' is 0x03.
but it does not! it always evaluates to 'false'.
a bitwise one's complement seems to return an undefined width, instead of a 8 bit value (unsigned char).

i found several workarounds to evaluate to true:

1) signed char a,b; (instead of unsigned) -> i really don't like signed char for logic operations

2) if (a == (unsigned char)~b) {/* true */}  -> seems to be the most efficient way

3) if (a == (~b & 0xff)) {/* true */}  -> requires more memory

although i found a workaround for the problem, i do not really understand why it does not automatically reduce the with to unsigned char, if only unsigned chars are involved.

i searche through my c reference book, but found nothing on this.

anyone knows?

thanx!
tino

2005\12\02@055039 by sergio masci

flavicon
face
part 1 1449 bytes content-type:TEXT/PLAIN; charset=UTF-8 (decoded quoted-printable)



On Fri, 2 Dec 2005, Buehler, Martin wrote:

{Quote hidden}

"b" is being promoted to "int" before the "~" is applied.


Regards
Sergio Masci

http://www.xcprod.com/titan/XCSB - optimising PIC compiler
FREE for personal non-commercial use



.


part 2 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2005\12\02@062345 by Buehler, Martin

picon face


******************************************************************************************************


>{Original Message removed}

2005\12\02@063842 by PY2NI TERRA

flavicon
face

   Well, using CC5X your fragment of code works as it should, no workaround
required,
   probably your compiler is pulling your leg somehow.

Horta


{Original Message removed}

2005\12\02@070711 by Gerhard Fiedler
picon face
Preamble: Everything I say depends a bit on the specific compiler and how
it implements implicit integer type promotions. I'm talking about ANSI C89,
assuming an int of 2 bytes (if the int is longer, like 4 bytes, it works
similar).

Buehler, Martin wrote:

> Why does a one's complement of an 'unsigned char' not return an 'unsigned
> char'?
Short answer: because all operations on types smaller than int are done as
ints. The results are then cast back when assigning to variables, but not
for subsequent operations that are not assignments.

Long answer:

> unsigned char a,b;
>
> a = 0x03; b = ~a;                //b = 0xfc
"b = ~a;" can also be written as

{
 int _internal_temp = a;
 _internal_temp = ~_internal_temp;
 b = (unsigned char)_internal_temp;
}

> if (a == ~b) {/* true */} else {/* false */}
>
> according to my understanding, this should always evaluate to 'true', as
> ´~b' is 0x03. but it does not! it always evaluates to 'false'. a bitwise
> one's complement seems to return an undefined width, instead of a 8 bit
> value (unsigned char).
The expression (a == ~b) gets evaluated like this:

{
 int _internal_temp_b = b; // high byte is 0, because b is unsigned
 _internal_temp_b = ~_internal_temp_b; // high byte is now 0xff
 int _internal_temp_a = a; // high byte is 0, because a is unsigned
 return (_internal_temp_a == _internal_temp_b);
}

The two internal temp variables are not the same. Their high byte is
different.


> i found several workarounds to evaluate to true:
Now applying the above to your workarounds:

> 1) signed char a,b; (instead of unsigned) -> i really don't like signed
> char for logic operations
Declaring a and b as signed changes the handling of the high bytes, because
the sign bit gets now extended into the high byte. The expression (a == ~b)
gets now evaluated like this:

{
 int _internal_temp_b = b; // high byte is 0xff, because b is signed and
negative
 _internal_temp_b = ~_internal_temp_b; // high byte is now 0
 int _internal_temp_a = a; // high byte is 0, because a is signed and
positive
 return (_internal_temp_a == _internal_temp_b);
}

This "works", but only because the values are as they are (a positive, b
negative). The "working" depends on the high bits (the sign) of a and b.
Dangerous and not recommended.

> 2) if (a == (unsigned char)~b) {/* true */}  -> seems to be the most
> efficient way
This not only works, but is also the cleaner way. After b gets implicitly
promoted to int for the ~ operation, you cast it back to the original type
(unsigned char) before the next operation (==). The result of this cast is
that you are comparing two unsigned chars, which get again promoted to int
for ==, but in the same way (with the high byte being 0 for both).

> 3) if (a == (~b & 0xff)) {/* true */}  -> requires more memory
That is similar to 2), but less clean, in that it only clears the high byte
of the int resulting from the expression ~b, whereas 2) also shows what's
really going on. Most optimizing compilers should generate the same code
for 2) and 3), though.

(BTW, since a byte is such a common type for embedded programming, it is
probably convenient to declare a type for it, instead of typing the
inconvenient "unsigned char" so often. I use an include file where I
declare the types u8, i8, u16, i16, u32, i32 -- which then are always what
they seem to say they are, independently of the particular compiler. :)


For more information, look for implicit conversions in a C standard and in
your compiler's manual.

Also note that many 8 bit compilers implement this (types and type
promotions) not 100% standard conform, so the results may vary depending on
the compiler. But in any case, your results can be explained by the
standard.

Gerhard

2005\12\02@074243 by Michael Rigby-Jones

picon face


>-----Original Message-----
>From: spam_OUTpiclist-bouncesTakeThisOuTspammit.edu [.....piclist-bouncesKILLspamspam@spam@mit.edu]
>Sent: 02 December 2005 12:04
>To: piclistspamKILLspammit.edu
>Subject: Re: [PIC] C-Compiler: One's complement of unsigned char
>
>
>(BTW, since a byte is such a common type for embedded
>programming, it is probably convenient to declare a type for
>it, instead of typing the inconvenient "unsigned char" so
>often. I use an include file where I declare the types u8, i8,
>u16, i16, u32, i32 -- which then are always what they seem to
>say they are, independently of the particular compiler. :)


It would be good practice to start using the C99 fixed integer size types rather than roll your own:

uint8_t
uint16_t
uint32_t
int8_t
int16_t
int32_t

Regards

Mike

=======================================================================
This e-mail is intended for the person it is addressed to only. The
information contained in it may be confidential and/or protected by
law. If you are not the intended recipient of this message, you must
not make any use of this information, or copy or show it to any
person. Please contact us immediately to tell us that you have
received this e-mail, and return the original to us. Any use,
forwarding, printing or copying of this message is strictly prohibited.
No part of this message can be considered a request for goods or
services.
=======================================================================

2005\12\02@074519 by William Chops Westfield

face picon face
On Dec 2, 2005, at 3:39 AM, PY2NI_TERRA wrote:

> using CC5X your fragment of code works as it should, no workaround
> required, probably your compiler is pulling your leg somehow.
>

x86 gcc behaves as described in the original post ("False" case.)
See Gerhard's excellent explanation; presumably cc5x uses 8bits for
"int", which is probably technically a standard violation but (IMO)
permissible or even useful for an embedded 8bit processor...

BillW

2005\12\02@084355 by Gerhard Fiedler

picon face
Michael Rigby-Jones wrote:

> It would be good practice to start using the C99 fixed integer size types
> rather than roll your own:
>
> uint8_t uint16_t uint32_t int8_t int16_t int32_t

Thanks for the tip; I might start doing that, or on second thought maybe
not...

I started with that before C99, and so far there are not many C99 compliant
compilers out there to really make a difference. If I should get to work
with one, it may just get simple typedefs in a common include file (I
always need one anyway). It's just a lot simpler to type u8 than it is to
type uint8_t... and I don't need the _t suffix; my editor knows how a
symbol is defined :)

Gerhard

2005\12\02@085229 by Buehler, Martin

picon face
thanx a lot!
i think i'll got it...
tino

******************************************************************************************************


>{Original Message removed}

2005\12\02@123916 by John Temples

flavicon
face
On Fri, 2 Dec 2005, Buehler, Martin wrote:

> Why does a one's complement of an 'unsigned char' not return an 'unsigned char'?

> i searche through my c reference book, but found nothing on this.

Look up "integer promotion" in your book.

--
John W. Temples, III

More... (looser matching)
- Last day of these posts
- In 2005 , 2006 only
- Today
- New search...