CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

int1 in struct does not evaluate properly in conditional

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
DireSpume



Joined: 07 Jan 2013
Posts: 31

View user's profile Send private message

int1 in struct does not evaluate properly in conditional
PostPosted: Mon Apr 15, 2013 6:32 pm     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Mon Apr 15, 2013 6:52 pm     Reply with quote

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: 19454

View user's profile Send private message

PostPosted: Tue Apr 16, 2013 12:46 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Apr 16, 2013 11:00 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Apr 16, 2013 6:23 pm     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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