|
|
View previous topic :: View next topic |
Author |
Message |
Ttelmah
Joined: 11 Mar 2010 Posts: 19542
|
|
Posted: Thu Jun 28, 2012 2:50 pm |
|
|
Aargh.
Can see exactly why Mike's code won't work.
This is down to one of the compiler changes made for ANSI compatibility. The functionality of two values 'anded' together, then put into a onebit value changes:
"
For CCS2:
onebit = eightbits is compiled as onebit = (eightbits != 0)
all other modes compile as: onebit = (eightbits & 1)
"
The two values anded are still an eight bit value, and the result is put into a one bit value, by testing the bottom bit only on the newer compilers, hence the slightly larger code, and it won't work right for anything but the bottom bit. On his older compiler it'll work. On the newer compiler, his version would need to be coded as:
Code: |
CLK_IN = 0;
DATA_IN = (no & 0X01)!=0 ;
CLK_IN = 0X01;
CLK_IN = 0;
DATA_IN = (no & 0X02)!=0 ;
CLK_IN = 0X01;
etc..
|
No point in using it, but nice to know 'why' it doesn't work.
Best Wishes |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Jun 28, 2012 3:52 pm |
|
|
I've already declared that I'm not a software expert, just a simple physicist.
I still don't quite follow.
Are you saying that this line:-
DATA_IN = no & 0X04 ;
Evaluates to either 0x01 or 0x00 with my older compiler but 0x04 or 0x00 with newer ones?
Mike |
|
|
khalis
Joined: 12 Feb 2009 Posts: 54
|
|
Posted: Thu Jun 28, 2012 6:48 pm |
|
|
Ttelmah... I got it now. Thanks for your quick explanation. Sorry took times to comprehend it. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Fri Jun 29, 2012 1:34 am |
|
|
Mike Walne wrote: |
Are you saying that this line:-
DATA_IN = no & 0X04 ;
Evaluates to either 0x01 or 0x00 with my older compiler but 0x04 or 0x00 with newer ones? |
Historical note:
C originally did not have a boolean type. It had integers, and floats but that is not relevant here. Conditions, i.e. in if statements and elsewhere such as the conditional parts of for statements, took integers as their parameters. Zero was taken as false, any non-zero value meant true. That essentially still holds true today.
Other languages had built-in boolean types which only have two possible values, true and false. C programmers tended to define values for true and false. False was 0 and true was... well, it was what the programmer wanted it to be, generally 1 as that was compatible with both signed and unsigned integers of any size, but occasionally -1 which obviously needed a signed int. That's OK as in most Cs int is signed by default. However its impossible to have a single bit signed integer, you need at least three bits to be any practical use in two's compliment notation.
Booleans were common extensions to many C implentations, but they were not "standard" until ANSI C made them so.
There are complications when casting from integers to booleans. The old favourite values of 0 and 1 obviosuly cause no issues, but what about 0x04? Well, that is "true" by the original C defintion and so you'd expect it to be cast to true, but as we know C doesn't normally automatically cast from the right hand to the left hand of assignments, you generally have to do it explicity. So it should perhaps not come as a surprise when such casting is not always quite as we expect.
In this case it seems likely, though I haven't trawled through the standards to confirm, that ANSI C defines, against the historical run of C, that such a implicit cast should be made automatically by the compiler. For simplicity, but technically incorrectly but then true K & R C didn't have booleans, it may well do that regardless of whether its in ANSI compatibility mode or not.
What I'm saying is that this sort of seemingly inconsistent behaviour is not quite so stupid as it sounds and may have historical language syntactical roots.
RF Developer |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19542
|
|
Posted: Fri Jun 29, 2012 3:32 am |
|
|
Just a little coda to this.
ANSI, _did not_ make boolean's standard. They are not supported/defined in the original definitions. It is only with C99, and later that they appear. It was also 'left floating' for a while, how they evaluated. They are now meant to behave as a single bit integer, corresponding to the low bit in a normal integer. Normally if you cast a int16, to an int8, this is done as (effectively)
int8val=int16val & 0xFF;
Upper bits are truncated (lost - except for 'signed', which is meant to propagate the sign bit).
The boolean's do exactly the same, so are evaluated effectively by testing just the low bit of the incoming value. There is no real core concept of them being a 'logical' value, so to convert an incoming int to this, you have to do the 'non zero' test. A caveat that is well worth being aware of.
What is 'wrong' in a sense, is that CCS, despite having 'reverse compatibility' modes with CCS2, and CCS3, elected to make the CCS3 mode switch to the later style, though the V3 compiler in reality didn't do this....
Fun....
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
|