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

Error with signed integer operations

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



Joined: 30 Jan 2008
Posts: 197

View user's profile Send private message

Error with signed integer operations
PostPosted: Wed Jul 07, 2021 6:54 pm     Reply with quote

Hi, I am use a Pic18F4620 with CCS compiler V4.074, I am doing a simple operation with signed integers of 8bits and 16 bits, the thing is that I have the variable "myRSSIValue8" that I collect from the array valueRSSI[] whose value is -77, but when I use this variable when doing the multiplication operation and add the value that I get it is 50, but when I do the same operation but instead using a constant (-77) the value I get is 18, why? What is my error?

Here is my code:
Code:
#include <18F4620.h>
#fuses HS,WDT32768,PROTECT,NOLVP,NOBROWNOUT
#use delay(clock=20MHz)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)// RS232 Estándar

int8 myCSQValue;
signed int8 myRSSIValue8;
signed int16 myRSSIValue16;
int16 myRSSIValuex;
char Buffer_ValRSSI[5];

char valueRSSI[]={-113,-110,-109,-107,-105,-103,-101,-99,-97,-95,-93,-91,-89,-87,-85,-83,-81,-79,-77,-75,-73,-71,-69,-67,-65,-63,-61,-59,-57,-55,-53}; 

void main(){
   myCSQValue = 18;
   myRSSIValue8 = valueRSSI[myCSQValue];
   myRSSIValue16 = ((4*(myRSSIValue8)) + 452)*0.125;   // Using a variable
   printf("myRSSIValue16:%04Ld\r\n",myRSSIValue16);

   myRSSIValue16 = ((4*(-77)) + 452)*0.125;         // Using a constant
   printf("myRSSIValue16:%04Ld\r\n",myRSSIValue16);


while (TRUE);
}
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Jul 07, 2021 7:38 pm     Reply with quote

my guess...
In CCS C 8 bit 'char' variables are UNsigned, ie 0 to 255
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 07, 2021 7:50 pm     Reply with quote

The values in bold below are both 8 bit, but the result is larger than 8 bits
so it's truncated, and you get the undesired result of -52.
Quote:
myRSSIValue16 = ((4*(myRSSIValue8)) + 452)*0.125;


To fix this problem, promote the RSSI variable to be signed 16-bits
as shown in bold below:
Quote:
void main(){
myCSQValue = 18;
myRSSIValue8 = valueRSSI[myCSQValue];
myRSSIValue16 = ((4*((signed int16)myRSSIValue8)) + 452)*0.125; // Using a variable
printf("myRSSIValue16:%04Ld\r\n",myRSSIValue16);

myRSSIValue16 = ((4*(-77)) + 452)*0.125; // Using a constant
printf("myRSSIValue16:%04Ld\r\n",myRSSIValue16);

pilar



Joined: 30 Jan 2008
Posts: 197

View user's profile Send private message

PostPosted: Wed Jul 07, 2021 7:51 pm     Reply with quote

Quote:
In CCS C 8 bit 'char' variables are UNsigned, ie 0 to 255


I have declared the array as a signed integer and I keep getting the same result, I don't understand why?

Code:
signed int8 valueRSSI[]={-113,-110,-109,-107,-105,-103,-101,-99,-97,-95,-93,-91,-89,-87,-85,-83,-81,-79,-77,-75,-73,-71,-69,-67,-65,-63,-61,-59,-57,-55,-53};
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 07, 2021 8:23 pm     Reply with quote

You missed my post given above.
pilar



Joined: 30 Jan 2008
Posts: 197

View user's profile Send private message

PostPosted: Wed Jul 07, 2021 8:44 pm     Reply with quote

PCM programmer, I am sorry, I had not seen your answer, yes you are right that was the problem

Thank you!
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Thu Jul 08, 2021 12:05 am     Reply with quote

As soon as I saw 'multiply', and signed 8bit, I thought 'overflow'. I see
PCM has spotted the same.

Can I make one alternate suggestion:
Code:

myRSSIValue16 = ((4L*myRSSIValue8) + 452)/8; // Using a variable


Two things to this. The problem comes about because in the multiplication,
anything over 63, will result in a signed int8 overflowing. Now when you
perform arithmetic in C, the original 'rules', were to use the 'highest' type
from the two values. So 4 (int8), times the signed 8bit myRSSIValue8, uses
signed 8bit arithmetic. Overflow. Now PCM has shown how to instead force
myRSSIValue8 to be treated as signed 16bit. Perfect answer. However the
compiler actually codes this a little less efficiently than if you do it the 'other
way round', and have the constant '4' declared as 16bit (4L). Since 'signed'
always has priority over 'unsigned', the result will be to use signed 16bit
arithmetic, and you should find the code is a little quicker, and smaller
doing it this way (only about one byte though!).
Then the second bit is the multiplication by 0.125.
Dividing by eight, instead makes it use int16 arithmetic again, and since
the result so far is already 'signed', this is done using signed int16.
Now, re-coding as I show, reduces this code (on a quick test compile),
from 674 bytes, to 376 bytes. It still gives the right result. Very Happy

Sizes of elements, and how this affects the arithmetic used, is a thing that
you really have to get your head around in C. Historically in all C's.
However in recent years, C's on things like the PC, have become rather
'forgiving' of this, since they use the hardware FPU, and so an int8 by
int8 multiplication will usually be using something like 80 bit registers
and overflows are automatically handled, and so don't give the problem
seen here!...

The 'saving' seen by the different approach depends on the processor used.
For some reason 'casts' seem to be very inefficient on the DsPIC's now,
which is why I try to avoid them. The speed gain is much bigger on the
PIC's that don't have hardware mul & div. On chips with these instructions
the original approach may well be nearly as fast, but the alternative is
still massively smaller. On chips without these instructions, the alternative
is nearly 50% faster!...
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