|
|
View previous topic :: View next topic |
Author |
Message |
simeon
Joined: 09 Apr 2005 Posts: 2
|
problems with negative integers? and some maths func perhaps |
Posted: Sat Apr 09, 2005 3:54 am |
|
|
i did notice a problem perhaps a bug.?
if i write code
like... below....
//
#include <STDLIB.H>
#include <stdio.h>
#include <math.h>
..
...
int count;
count = 8;
while (count >= 0)
{
..
...
count--;
}
//
and the integer count eqiuals -1 after 9 events
this state is never reached and the subfunction while{} will never terminate
logicaly it should,
in terms of maths and other c and ansi c compilers.
can you let me know if this is a known limitation or a bug
however the way i used was this
//
#include <STDLIB.H>
#include <stdio.h>
#include <math.h>
..
...
int count;
count = 8;
while (count != -1)
{
..
...
count--;
}
//
and this works fine and the while does indeed terminate after 9 events
althought not as nice and neet and logical as the one above it, it did work ok...
perhaps picc has a flaw in its maths aspects of zero
or how it handles negative integers....? when challanged with a greater than paradymn.
all very strange and unexpected
i look foward to any reply TIA |
|
|
Ttelmah Guest
|
|
Posted: Sat Apr 09, 2005 4:00 am |
|
|
As written, it will not work on some other compilers either.....
The reason, it will work on some, is down to the decision about what is a 'default' integer. Some compilers default to using a signed integer, and on these it will work. The CCS default integer, is unsigned, and on any compiler where this is true, it should not work.
This is why you should use explicit types. Personally, I never use 'int', unless the size/sign will not matter. Use int8, int16, and int32, so you know what size the values are (since these are also supported in most modern compilers), and add 'unsigned', or 'signed' to each (though the former is unecessary in CCS, since it is the default, declaring it explicitly, costs nothing, and _ensures_ you get the type you want if you move the code to another compiler.
Best Wishes |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Sat Apr 09, 2005 11:05 am |
|
|
Actually, I've noticed that it doesn't matter if the integer is declared as signed or unsigned, the compiler can't properly handle ">" or "<" in tests if you are expecting negative numbers.
I haven't tested this with the latest version of the compiler, but I know for sure that 3.178 had this flaw. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Apr 09, 2005 11:19 am |
|
|
Quote: |
Actually, I've noticed that it doesn't matter if the integer is declared as
signed or unsigned, the compiler can't properly handle ">" or "<" in tests
if you are expecting negative numbers. |
Can you post a test program that shows that problem ? |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Sat Apr 09, 2005 11:40 am |
|
|
Hmmm... thats strange, I have never seen this problem... Must have been lucky :-) Gonna go back myself and see if I can reproduce it.
Anyone else seen it? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Sat Apr 09, 2005 1:59 pm |
|
|
I tried to replicate the problem, and I was sort of able to do it. I know for a fact that I had a devil of a time with this about a year ago and that in order to properly test if a signed integer was < 0, I'd have to test to see if the msb was set. Simply doing a "if (xxx < 0)" never worked. It's like the compiler was doing the relational stuff using only unsigned integer math.
Now that I think of it, it may have been a casting problem. I saw this happen when I was using the built-in A/D. I was reading an analog signal, and the signal can lie within a certain range. I needed to know if it was out of range. I was testing to see if the result of the reading - lower threshold was negative (below range), and it never was, even if the reading was below the lower threshold. Stupid me, I bet that I didn't use signed integers to do it, or mixed signed & unsigned integers. In fact, that's most likely what I did. I simply used unsigned integers to store the A/D reading, and didn't do the casting properly.
Anyway, here's some code that I whipped up to try and replicate the problem. I was able to duplicate what I was likely seeing in one of the cases:
Code: | #include <18F452.h>
#device adc=8
#fuses WDT,WDT1, XT, NOPROTECT, NOOSCSEN, BROWNOUT, BORV20, PUT, STVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use delay(clock=4000000,RESTART_WDT)
#include "i:\ELEN\LCD Task\lcd_driver.c"
unsigned int8 a = 3, b = 227;
signed int8 c = -9, d = 100, i;
void main() {
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_wdt(WDT_ON);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
set_tris_e(0x00);
lcd_init();
lcd_putc("\f");
while (TRUE) {
restart_wdt();
// first test - both unsigned
lcd_putc("\fa < b ");
if (a < b) {
lcd_putc("True");
}
else {
lcd_putc("False");
}
delay_ms(1000);
// second test - both signed
lcd_putc("\fc < d ");
if (c < d) {
lcd_putc("True");
}
else {
lcd_putc("False");
}
delay_ms(1000);
// third test - mix
lcd_putc("\fc < a ");
if (c < a) {
lcd_putc("True");
}
else {
lcd_putc("False");
}
delay_ms(1000);
// fourth test - mix
lcd_putc("\fd < b ");
if (d < b) {
lcd_putc("True");
}
else {
lcd_putc("False");
}
delay_ms(1000);
// fifth test - less than 0
lcd_putc("\fc < 0 ");
if (c < 0) {
lcd_putc("True");
}
else {
lcd_putc("False");
}
delay_ms(1000);
// sixth test - mix
lcd_putc("\fc < b ");
if (c < b) {
lcd_putc("True");
}
else {
lcd_putc("False");
}
delay_ms(1000);
// let's try to screw it up
d = b;
lcd_putc("\fc < d ");
if (c < d) {
lcd_putc("True");
}
else {
lcd_putc("False");
}
delay_ms(1000);
// do a test on a while loop
i = 10;
while (i > 0) {
restart_wdt();
printf(lcd_putc,"\fi = %d",i);
delay_ms(200);
i--;
}
}
} |
When the program runs, everything evaluates as it should until it gets to the part where I say "let's try to screw it up." There, I try to store 227 in a signed int8, where it is now interpreted as -29. Now the test "is -9 < -29" evaluates to false. Technically, this is correct, but it could sure throw you for a loop if you're (incorrectly) assuming that d is 227.
Thanks everyone - you made me think (no small feat).
It's nice to finally put this "mystery" to rest. |
|
|
simeon
Joined: 09 Apr 2005 Posts: 2
|
|
Posted: Sun Apr 10, 2005 8:13 am |
|
|
one of the replys above about adc enabled etc
yes i use all analog in that routine
however it didnt answer my question
what ever cast an int is makes no differance here
as i type define anyway in headers
and the compiler will choose most often
i recon its a problem with the scope of the int and maths.inc
as i was using several functions at the same time
however it still should work
no matter i solved the problem anyway and the code works ok
thanks everyone for an interesting read and for taking the time you did
to solve this issue
|
|
|
Ttelmah Guest
|
|
Posted: Sun Apr 10, 2005 2:09 pm |
|
|
As I tried to say before, it is simply the way that unsigned integers work in this implementation. When you decrement an unsigned int8, from 0, it goes to 255. Hence it will never test as '<=0'. Technically, you can generate exactly the same behaviour in most C's with an unsigned type, by turning off maths error checking, and many other embedded versions do exactly the same. Historically, there was a problem with comparison (as opposed to equality) testing, in some older versions of the CCS C, but it works fine now. The reason that the comparison with '-1' works, is that '-1', is stored as 0B11111111. which is the same binary value as 255 in an unsigned. This C does not implement maths error checking. If you want this, you would have to add the extra code yourself, and the size involved, makes it undesirable in most situations.
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
|