View previous topic :: View next topic |
Author |
Message |
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
SWITCH-CASE bug with signed long on 5.026? |
Posted: Thu Oct 20, 2016 6:45 am |
|
|
Compiler: 5.026
Device: PIC24EP512GP806
Unless I misread or misunderstood something, I just tried a switch/case statement and the value being checked is a <signed long> and if I pass a negative value, it is ignored therefore I suspect the switch/case statement to only accept <unsigned int8> or has a bug?
Example:
Code: |
void MyFunction( signed long MyValue )
{
fprintf( SERIAL, "MyValue (Initial): %Ld", MyValue );
switch( MyValue )
{
case -1:
{
fprintf( SERIAL, "MyValue (switch -1): %Ld", MyValue );
// This case statement is not seen and is skipped
}
break;
case 0:
{
fprintf( SERIAL, "MyValue (switch 0): %Ld", MyValue );
// This case statement is seen
}
break;
case 255:
{
fprintf( SERIAL, "MyValue (switch 255): %Ld", MyValue );
// This case statement is seen when MyValue is -1
}
break;
}
} |
So in the above function, this is what I get as an output:
MyValue (Initial): -1
MyValue (switch 255): 255
In MyFunction, the values passed are #defines:
Code: |
#define ValueNeg -1
#define ValueZero 0
#define Value255 255 |
And if I replace the switch/case by a standard if statement, then it works.
Ben |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Thu Oct 20, 2016 7:14 am |
|
|
I don't know for sure what is, or isn't going on. One thing I do notice is: what do you think the size of "unsigned long" is on PIC24s with CCS? Hint: it is not the same as on 18/16/12s.
It would not surprise me that CCS C assumes expressions for switches are unsigned, as that is the default for int for many versions of the compiler. In other words, there may be a "hangover" from other implementations of the compiler. It would surprise me that int8 was the only acceptable size. I am pretty sure sixteen bit values can be used in switches. I'm not convinced about 32 bit values, hence my comment above.
Switches are not implemented the same way in all cases, it depends a lot on the type of the selector variable and on the number of cases, and on whether there is a default or not. In some cases a switch will be implemented in much the same way as a if-ladder, sometimes by a jump table and sometimes by other means.
Also, I not at all sure that all types would be acceptable in switches. For example I am not at all sure how floats would behave when used aas the selector. I assume a bit for bit comparison is used (or effectively so), so provided floats were normalised there shouldn't be a problem... should there? Even so, I would not recommend float selectors, and regard it a "bad form" and derogate it as a programming practise, much as we do in precise float comparisons.
Last edited by RF_Developer on Thu Oct 20, 2016 7:20 am; edited 1 time in total |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Thu Oct 20, 2016 7:17 am |
|
|
Fair enough. Anyhow I just thought I'd post it here in case anyone else runs into the same situation.
Since I am only evaluating 3 values, the good'old <if> statement works just fine.
Thanks.
Ben |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19557
|
|
Posted: Thu Oct 20, 2016 7:37 am |
|
|
Are you sure you need an int32?.
On your compiler, the default integer is a signed iint16, and this is the default type used behind the switch statement.
Basically the test values are stored as and tested as int16 values.
It'll work if you cast your value to an int16 (avoid using 'long', since it has different meanings on different compilers - always much safer to be explicit on the sizes you use). So:
Code: |
switch((signed int16) MyValue )
|
That the type used in switch is the default integer, is actually in the C standard. However CCS stretch it for the 8bit PIC's now and do accept int16. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Thu Oct 20, 2016 8:35 am |
|
|
Ah! You are correct! I didn't realize that by using a 'long' I was using a 32-bit number. I changed it to a signed int16.
Thanks!
Ben |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Thu Oct 20, 2016 9:26 am |
|
|
As a point of interest, if you change your first case statement from -1 to some number larger than a 16 bit number (like 80000) it will generate a compiler error saying that the number is out of range. So this indicates (and reinforces what was said earlier) that the switch statement can only handle int16 sized or lower case values. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9249 Location: Greensville,Ontario
|
|
Posted: Thu Oct 20, 2016 9:40 am |
|
|
re:...
Quote: | the switch statement can only handle int16 sized or lower case values. |
um, what about UPPER case values ?? LOL.
Hay, you made my day !
I KNOW what you meant, just funny to me 'lower case values'......
I'd have thought 'switch' vales had to be unsigned integers, say 16 bit max, in order to be fast to compare....
cheers
Jay |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Thu Oct 20, 2016 11:07 am |
|
|
Glad to bring some joy!
This thread also reminded me why our coding standards require us to use the sized types (int8, int16, int32) for numeric and raw data. Normally we ban the use of "long" and "int" unless there is a specific reason to use them. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19557
|
|
Posted: Thu Oct 20, 2016 1:30 pm |
|
|
Signed makes no difference to the compare. -1 (int16) codes as 0xFFFF, and it is this that the test compares to.
Agree wholeheartedly with Jeremiah. Once you move between different processors and languages, being 'explicit' on sizes become essential. |
|
|
|