|
|
View previous topic :: View next topic |
Author |
Message |
Leef_me
Joined: 14 Mar 2006 Posts: 45
|
Trouble with 16 and 32 bit math |
Posted: Fri Dec 17, 2010 4:03 am |
|
|
1. I am getting different results from the rr1 and rr2 variables.
The values I see when running through the code to a breakpoint show the results listed in the comments.
Why is the calculation for rr1 incorrect?
What am I missing?
2. When I first started debuging this code as an example, the 2nd assignment to o[0] resulted in 0 in the watch window.
Shouldn't the result from the two o[0] statements be identical?
Later, the results appear the same; and I can't recreate the alternate circumstances.
Thanks in advance.
Leef_me
Code: |
#include "18F26K20.h"
#device ICD=TRUE
#FUSES NODEBUG //No Debug mode for ICD
#fuses INTRC_IO //Internal Oscillator, free RA6 and RA7 for i/o operations
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES MCLR //Master Clear pin enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(clock=16000000) //16mhz
void main(void)
{
int8 temp;
signed int32 rr1,rr2;
static signed int16 c[] = {11059};
signed int16 o[1];
o[0]=2748; // <---- are these the same ?
o[0]=2748L; // <---- are these the same ?
rr1 = o[0] * c[0]; // <---- wrong math result is 4294948724
rr2 = o[0]; // <--- correct math
rr2 = rr2 * c[0]; // <--- correct math result is 30390132
temp++;
temp++; // just a place to add a breakpoint
temp++;
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri Dec 17, 2010 4:17 am |
|
|
Exactly what would be expected.....
_Standard C_. In C, the compiler looks at what values are given for both 'sides' of an arithmetic operation, and uses the arithmetic 'type' defined by the 'higher' of these. In:
rr1 = o[0] * c[0];
Both of the variables each side of the '*', are signed int16, so signed int16 arithmetic _will_ be used, and overflow. This will then be cast to an int32 result, and will be wrong.
In the second case, rr2, is a signed int32, so the arithmetic type will change to signed int32, and no overflow results.
rr1 = (signed int32)o[0] * c[0];
This will convert the first value to a signed int32, and thereby make the compiler use this as the arithmetic type.
The problem is being caused by _you_ not thinking 'how big might the result be', and ensuring the right maths type is used.
You may get away with this error on a lot of later C's, on things like the PC, since here the maths will be done using the hardware, which handles overflows automatically (in some cases....). However to be safe, you should _always_ ensure that the maths type used is able to handle the values needed.
2748, and 2748L are the same. The 'L' forces a value to be treated as a 'long', when it is not 'obvious' from the number involved. So:
123L, is in hex 0x007B, while:
123, is 0x7B
Note the extra leading zeros. The 'L' is forcing the value to be treated as a 16bit value. However if the number is over 255, such treatment is 'automatic'.
Best Wishes |
|
|
Leef_me
Joined: 14 Mar 2006 Posts: 45
|
|
|
|
|
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
|