|
|
View previous topic :: View next topic |
Author |
Message |
DireSpume
Joined: 07 Jan 2013 Posts: 31
|
int1 in struct does not evaluate properly in conditional |
Posted: Mon Apr 15, 2013 6:32 pm |
|
|
It seems like I found a compiler bug (PCH 4.140 on PIC18F67K22). My understanding is that an int1 should get automatically converted to an int8 if it gets used with any non-boolean operator. However, that doesn't seem to be happening when using uint1s that are members of a struct. If I compare the member uint1 to another uint1 using !=, it does not evaluate correctly. Also, printf() also doesn't seem to handle uint1s properly if they are struct members unless accessing with '.' rather than '->'. Actually, using '.' to access members (i.e. non-pointer access) may work fine for the != operator as well, but I don't feel like testing that now. This is enough to show the problem.
Here is the code:
Code: |
typedef int1 bool;
#define true 1
#define false 0
typedef struct {
int32 Interval;
bool LastVal, RetVal;
} DeBounceData;
void GetDeBouncedVal(DeBounceData* data, bool curVal)
{
printf("CurVal = %u; LastVal = %u; RetVal = %u\r\n", curVal, data->LastVal, data->RetVal);
if (curVal != data->LastVal)
printf("ONE\r\n");
if ((curVal && !data->LastVal) || (!curVal && data->LastVal))
printf("TWO\r\n");
}
void main()
{
DeBounceData DVal;
while (true)
{
delay_ms(1000);
DVal.LastVal = false;
DVal.RetVal = true;
printf("LastVal = %u, RetVal = %u\r\n", DVal.LastVal, DVal.RetVal);
GetDeBouncedVal(&DVal, false);
GetDeBouncedVal(&DVal, true);
DVal.LastVal = true;
DVal.RetVal = false;
printf("LastVal = %u, RetVal = %u\r\n", DVal.LastVal, DVal.RetVal);
GetDeBouncedVal(&DVal, false);
GetDeBouncedVal(&DVal, true);
}
}
|
And here is the output:
Quote: |
LastVal = 0, RetVal = 1
CurVal = 0; LastVal = 0; RetVal = 0 <---- printf() WRONG, RetVal = 1
ONE <------ != WRONG, CurVal is == to LastVal
CurVal = 1; LastVal = 0; RetVal = 0 <---- printf() WRONG, RetVal = 1
ONE
TWO
LastVal = 1, RetVal = 0
CurVal = 0; LastVal = 1; RetVal = 1 <---- printf() WRONG, RetVal = 0
ONE
TWO
CurVal = 1; LastVal = 1; RetVal = 1 <---- printf() WRONG, RetVal = 0
<----- != evaluates correctly here for some reason (no 'ONE')
|
Is this a known bug? Or not a bug at all and I'm just being stupid? By the way, explicitly casting to a int8 doesn't help (although it does make the printf() print RetVal as 2 when its 1, and 1 when it's 0. Weird!). |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Apr 15, 2013 6:52 pm |
|
|
Have you checked the .LST file to see if the problem is NOT in the
STRUCT compound definition of a typedef (bool) in a subsequent tyepdef struct ??
The .LST file could answer the question you pose, as i see more than one
possible explanation for your issue.
'naked' INT1 var types( not typdefed as bool i mean ) work properly, do they not ?? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19494
|
|
Posted: Tue Apr 16, 2013 12:46 am |
|
|
Try searching the forum...
Known bug. Has been fixed in 4.141, but there are still problems with arrays of int1's inside structures.
Basically int1's don't always reliably get propagated if used in logic/arithmetic.
Typedef isn't the cause, it applies to int1's across the board.
You can force propagation with a cast, and it then works.
int1's only work reliably 'stand alone'. If you want to use them in arrays, or structures, then copy them 'out', and perform the operations on the copied values.
However realistically for what you want, use the traditional C declaration and a bitfield:
Code: |
typedef struct {
int32 Interval;
int8 LastVal:1;
int8 RetVal:1; //generate two one bit bitfields
} DeBounceData;
|
Supported by other C's, and more reliable.....
Best Wishes |
|
|
DireSpume
Joined: 07 Jan 2013 Posts: 31
|
|
Posted: Tue Apr 16, 2013 11:00 am |
|
|
Thanks Ttelmah. I tried searching the forum first, but I guess I suck at searching. Casting to int8 didn't work for me. I'll do it as a bit field... good call. |
|
|
DireSpume
Joined: 07 Jan 2013 Posts: 31
|
|
Posted: Tue Apr 16, 2013 6:23 pm |
|
|
Oops, I spoke too soon. Bit fields appear to have the same problem! I changed the bools in the struct to single bits as a bit-field, but left all the other code the same, and I get exact same output as with bools.
Code: |
typedef struct {
int32 Interval;
uint8 LastVal : 1;
uint8 RetVal : 1;
} DeBounceData;
|
The workaround I'm using that seems to work well is to always use a boolean operator on the bool member first, before using a non-boolean operator. So instead of "if (curVal != data->LastVal)", I can use "if (curVal == !data->LastVal)", and that works as expected. |
|
|
|
|
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
|