|
|
View previous topic :: View next topic |
Author |
Message |
red_one
Joined: 30 Nov 2007 Posts: 10
|
issue with unsigned 16 bits integer |
Posted: Mon Dec 17, 2007 7:55 pm |
|
|
type def.
Code: | typedef unsigned int uint16_t; |
declaration
initialization
test
Code: | if (x == 0x00FF)
printf("oops\r\n");
if (x == 0xFFFF)
printf("OK\r\n"); |
it prints oops and OK all time.
what's wrong ??
I'm using CCS proto board with PIC16F877A mcu and PICC version 4.064
Last edited by red_one on Mon Dec 17, 2007 8:19 pm; edited 1 time in total |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: issue with unsigned 16 bits integer |
Posted: Mon Dec 17, 2007 8:11 pm |
|
|
red_one wrote: |
Code: | if (x == 0x00FF);
printf("oops\r\n");
if (x == 0xFFFF)
printf("OK\r\n"); |
it prints oops and OK all time.
what's wrong ??
|
Hint: Look closely at the semicolon after your first "if" statement....
Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
Guest
|
Re: issue with unsigned 16 bits integer |
Posted: Mon Dec 17, 2007 8:18 pm |
|
|
RLScott wrote: | red_one wrote: |
Code: | if (x == 0x00FF);
printf("oops\r\n");
if (x == 0xFFFF)
printf("OK\r\n"); |
it prints oops and OK all time.
what's wrong ??
|
Hint: Look closely at the semicolon after your first "if" statement....
Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
it's just a past mistyping ! |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Re: issue with unsigned 16 bits integer |
Posted: Mon Dec 17, 2007 9:33 pm |
|
|
red_one wrote: | type def.
Code: | typedef unsigned int uint16_t; |
|
What is an int?
It's a value with no fractional component.
In the context of programming in C it is the internal bus with of the target processor. A PIC microchip has an 8-bit internal bus. So you are declaring a byte variable with the name uint16_t . You actually don't need to do a typedef. int16 is a unsigned 16bit variable. |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: issue with unsigned 16 bits integer |
Posted: Tue Dec 18, 2007 6:47 am |
|
|
Anonymous wrote: |
Quote: |
Code: | if (x == 0x00FF);
printf("oops\r\n");
if (x == 0xFFFF)
printf("OK\r\n"); |
it prints oops and OK all time.
what's wrong ??
Hint: Look closely at the semicolon after your first "if" statement....
|
it's just a past mistyping ! |
Are you sure it is not in the actual code that is causing the problem? Because it does explain the reported behavior completely.
Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
Guest
|
Re: issue with unsigned 16 bits integer |
Posted: Tue Dec 18, 2007 9:39 am |
|
|
RLScott wrote: | Anonymous wrote: |
Quote: |
Code: | if (x == 0x00FF);
printf("oops\r\n");
if (x == 0xFFFF)
printf("OK\r\n"); |
it prints oops and OK all time.
what's wrong ??
Hint: Look closely at the semicolon after your first "if" statement....
|
it's just a past mistyping ! |
Are you sure it is not in the actual code that is causing the problem? Because it does explain the reported behavior completely.
Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
I'm sure.
Another issue.
Code: | uint16_t x;
x=0xFFFF;
printf("x=%ld\r\n", x); |
it prints x=-1
and doesn't compile when I replace %ld with %d.
%ld is for long integer (4 bytes), isn't it ?
I thought unsigned int16 variables are unsigned 2 bytes integer.
I don't understand what's wrong.
How to have UNSIGNED 16 bits integer ? |
|
|
Ttelmah Guest
|
|
Posted: Tue Dec 18, 2007 9:55 am |
|
|
rtfm.....
%ld, is the declarator to print the number as a _signed_ long.
%lu, is the declarator to print an unsigned long.
Best Wishes |
|
|
Guest
|
|
Posted: Tue Dec 18, 2007 10:58 am |
|
|
Ttelmah wrote: | rtfm.....
%ld, is the declarator to print the number as a _signed_ long.
%lu, is the declarator to print an unsigned long.
Best Wishes |
As far as I know unsigned int16 isn't long integer.
why it compiles with %ld ?? |
|
|
frequentguest Guest
|
|
Posted: Tue Dec 18, 2007 11:09 am |
|
|
A long is an in16 is and unsigned 16-bit integer.
Check out the help file/manual on the basic types in CCS. |
|
|
frequentguest Guest
|
|
Posted: Tue Dec 18, 2007 11:12 am |
|
|
Quote: | A long is an in16 is and unsigned 16-bit integer.
Check out the help file/manual on the basic types in CCS. |
Wow, I guess I need to start checking a little better before I post. That should read:
A long is an int16 which is an unsigned 16-bit integer... |
|
|
Ttelmah Guest
|
|
Posted: Tue Dec 18, 2007 11:39 am |
|
|
The concepts of 'length', and 'sign', are separate. You can have a signed long, or a unsigned long (the default in CCS, is for types to be _unsigned_, unless otherwise specified). Similarly, you can have a normal 8bit value, that is either signed or unsigned. The 'l' specifier, added to the printf, tells the compiler that the value will be a 'long'. The 'u' specifier, says it is dealing with an unsigned type.
The printout definitons, are _distinct_ from the data definitions, and this is a 'weakly typed' language, so errors in typing are _not_ complained about. So:
Code: |
int16 uval; //declare an unsigned int16
signed int16 val; //declare a signed int16
float fp_val;
val=-1;
printf("value treated as signed %ld\n\rtreated as unsigned %lu",val,val);
//You will see -1, and 65535 displayed.
uval=val;
fpval=val;
printf("\n\rresult from converting to a float from the signed %f\n\r",fpval);
//You will get -1
fpval=uval;
printf("result from converting the same value stored in an int16 %f",fpval);
//you will get 65535.....
|
Here you will see the hex value 0xFFFF, treated both as -1, and as 65535, in the first case, switched by the output declaration in printf, and latter, handled 'automatically', because of the data type.
Best Wishes |
|
|
red_one
Joined: 30 Nov 2007 Posts: 10
|
|
Posted: Wed Dec 19, 2007 5:11 am |
|
|
Code: | typedef unsigned int16 uint16_t;
uint16_t x = 0xFFFF; |
well.
I still have 255 instead of 65535 when wathching in the debugger |
|
|
Ttelmah Guest
|
|
Posted: Wed Dec 19, 2007 9:28 am |
|
|
And did you change the debugger settings for the variable, to tell it that this was a 1bit value now, not an 8bit one.
Most default to assuming a value is 8bit, not 16bit.
Best Wishes |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: issue with unsigned 16 bits integer |
Posted: Wed Dec 19, 2007 8:29 pm |
|
|
Anonymous wrote: |
Code: | if (x == 0x00FF);
printf("oops\r\n");
if (x == 0xFFFF)
printf("OK\r\n"); |
it prints oops and OK all time.
what's wrong ??
it's just a past mistyping ! [meaning the ";" after the "if"]
I'm sure.
|
I think you have discovered a compiler bug. Here is the situation.
Your typedef defines a new type, inappropriately named uint16_t, which is actually just an int. On the 16Fxxx family of PICs, an int is 8 bits. So x is only an unsigned 8-bit quantity (0 to 255). The assignment of x = 0xFFFF just assigns the low-order 8 bits to x, or 255. The first comparison, (x == 0x00FF) compares two values that are both expressible in 8 bits, so the comparison yields "TRUE". The second comparison is with an 8-bit x and a 16-bit 0xFFFF. By the rules of C, this should result in promoting the 8-bit quantity to 16-bits and then making the comparison with 16 bits. But I have examined the disassembly listing after compiling this code, and I see that the compiler actually demotes the 0xFFFF down to 8 bits by discarding the high-order byte, and then the comparison takes place with 8 bits, with of course again yields "TRUE". So you were right all along. In fact, you would have gotten a TRUE comparison even if you wrote (x == 0x34FF).
Interestingly, the compiler bug is confined to the case where the 16-bit number is a constant. If the 16-bit number is a variable, then the compiler does the right thing and promotes x to 16 bits before making the comparison.
Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
Ttelmah Guest
|
|
Posted: Thu Dec 20, 2007 5:06 am |
|
|
Yes.
If you look at the top line of the manual entry for 'how are type conversions handled', it says that:
"For example: int8var = int16var; Causes the top byte of int16var to be lost.".
The arithmetical precedence for '==', is actually less that for '=', so it makes a sort of sense....
In fact you have to distinguish here, the behaviour of the 'preprocessor', which is attampting to simplify operations before the main compiler phase, and it simply decides that there is no mathematical operation on the line using int16, so casts everything to int8, before starting.
It really would justify a warning (the compiler does actually generate one, if you use the '>' test, rather than the '==' test, warning that the condition can never be true).
Most compilers, don't actually return 'true' for the first, and 'false' for the second. You have to remember when testing this, that on 90%+ of compilers, the 'default' arithmetic type, is an int16, not int8. If you perform the equivalent test (using a int32 constant, and comparing with an int16 variable), the commonest behaviour is to warn (4), and the rest actually behave as the CCS compiler does (2), but only when dealing with these larger data types... I tried six different 'C' compilers just for interest'.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|