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 CCS Technical Support

problems with negative integers? and some maths func perhaps

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



Joined: 09 Apr 2005
Posts: 2

View user's profile Send private message

problems with negative integers? and some maths func perhaps
PostPosted: Sat Apr 09, 2005 3:54 am     Reply with quote

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







PostPosted: Sat Apr 09, 2005 4:00 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Apr 09, 2005 11:05 am     Reply with 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.

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

View user's profile Send private message

PostPosted: Sat Apr 09, 2005 11:19 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Apr 09, 2005 11:40 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Apr 09, 2005 1:59 pm     Reply with quote

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). Laughing

It's nice to finally put this "mystery" to rest.
simeon



Joined: 09 Apr 2005
Posts: 2

View user's profile Send private message

PostPosted: Sun Apr 10, 2005 8:13 am     Reply with quote

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

Cool
Ttelmah
Guest







PostPosted: Sun Apr 10, 2005 2:09 pm     Reply with quote

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