thanx a lot! i think i'll got it... tino *************************************************************************= ***************************** >-----Original Message----- >From: piclist-bounces@mit.edu [mailto:piclist-bounces@mit.edu]=20 >On Behalf Of Gerhard Fiedler >Sent: Friday, December 02, 2005 1:04 PM >To: piclist@mit.edu >Subject: Re: [PIC] C-Compiler: One's complement of unsigned char > > >Preamble: Everything I say depends a bit on the specific=20 >compiler and how it implements implicit integer type=20 >promotions. I'm talking about ANSI C89, assuming an int of 2=20 >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=20 >> 'unsigned char'? > >Short answer: because all operations on types smaller than int=20 >are done as ints. The results are then cast back when=20 >assigning to variables, but not for subsequent operations that=20 >are not assignments. > >Long answer: > >> unsigned char a,b; >>=20 >> a =3D 0x03; b =3D ~a; //b =3D 0xfc=20 > >"b =3D ~a;" can also be written as > >{ > int _internal_temp =3D a; > _internal_temp =3D ~_internal_temp; > b =3D (unsigned char)_internal_temp; >} > >> if (a =3D=3D ~b) {/* true */} else {/* false */} >>=20 >> according to my understanding, this should always evaluate=20 >to 'true',=20 >> as =B4~b' is 0x03. but it does not! it always evaluates to 'false'. a=20 >> bitwise one's complement seems to return an undefined width, instead=20 >> of a 8 bit value (unsigned char). > >The expression (a =3D=3D ~b) gets evaluated like this: > >{ > int _internal_temp_b =3D b; // high byte is 0, because b is unsigned > _internal_temp_b =3D ~_internal_temp_b; // high byte is now 0xff > int _internal_temp_a =3D a; // high byte is 0, because a is unsigned > return (_internal_temp_a =3D=3D _internal_temp_b); >} > >The two internal temp variables are not the same. Their high=20 >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=20 >> signed char for logic operations > >Declaring a and b as signed changes the handling of the high=20 >bytes, because the sign bit gets now extended into the high=20 >byte. The expression (a =3D=3D ~b) gets now evaluated like this: > >{ > int _internal_temp_b =3D b; // high byte is 0xff, because b is=20 >signed and negative > _internal_temp_b =3D ~_internal_temp_b; // high byte is now 0 > int _internal_temp_a =3D a; // high byte is 0, because a is=20 >signed and positive > return (_internal_temp_a =3D=3D _internal_temp_b); >} > >This "works", but only because the values are as they are (a=20 >positive, b negative). The "working" depends on the high bits=20 >(the sign) of a and b. Dangerous and not recommended. > >> 2) if (a =3D=3D (unsigned char)~b) {/* true */} -> seems to be the mo= st=20 >> efficient way > >This not only works, but is also the cleaner way. After b gets=20 >implicitly promoted to int for the ~ operation, you cast it=20 >back to the original type (unsigned char) before the next=20 >operation (=3D=3D). The result of this cast is that you are=20 >comparing two unsigned chars, which get again promoted to int=20 >for =3D=3D, but in the same way (with the high byte being 0 for both). > >> 3) if (a =3D=3D (~b & 0xff)) {/* true */} -> requires more memory > >That is similar to 2), but less clean, in that it only clears=20 >the high byte of the int resulting from the expression ~b,=20 >whereas 2) also shows what's really going on. Most optimizing=20 >compilers should generate the same code for 2) and 3), though. > >(BTW, since a byte is such a common type for embedded=20 >programming, it is probably convenient to declare a type for=20 >it, instead of typing the inconvenient "unsigned char" so=20 >often. I use an include file where I declare the types u8, i8,=20 >u16, i16, u32, i32 -- which then are always what they seem to=20 >say they are, independently of the particular compiler. :) > > >For more information, look for implicit conversions in a C=20 >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=20 >depending on the compiler. But in any case, your results can=20 >be explained by the standard. > >Gerhard > >--=20 >http://www.piclist.com PIC/SX FAQ & list archive >View/change your membership options at=20 >http://mailman.mit.edu/mailman/listinfo/piclist > --=20 http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist