|
|
View previous topic :: View next topic |
Author |
Message |
Guest
|
int/long compiler bug? |
Posted: Fri Jan 25, 2008 6:49 pm |
|
|
I'm admittedly not a big-time C language nerd, but it seems to me that the two examples below might illustrate a bug.
If my lvalue is of type long, and I cast the result of a multiply as 'long', shouldn't the computation be done in order to assure a proper 16 bit result? Seems unintuitive that I should have to cast the 'int' in the mutiply instead...
#define PRESET_SIZE 100
int presetNumber;
long presetAddr;
4096: presetAddr = (long)(presetNumber * PRESET_SIZE);
74E6 0107 MOVLB 0x7
74E8 511B MOVF 0x1b, W, BANKED
74EA 0D64 MULLW 0x64
74EC 50F3 MOVF 0xff3, W, ACCESS
74EE 6B1E CLRF 0x1e, BANKED
74F0 6F1D MOVWF 0x1d, BANKED
4064: presetAddr = ((long)presetNumber * PRESET_SIZE);
7250 0107 MOVLB 0x7
7252 6B24 CLRF 0x24, BANKED
7254 C71B MOVFF 0x71b, 0x723
7258 6A18 CLRF 0x18, ACCESS
725A BCF2 BTFSC 0xff2, 0x6, ACCESS
725C 8C18 BSF 0x18, 0x6, ACCESS
725E 9CF2 BCF 0xff2, 0x6, ACCESS
7260 BEF2 BTFSC 0xff2, 0x7, ACCESS
7262 8E18 BSF 0x18, 0x7, ACCESS
7264 9EF2 BCF 0xff2, 0x7, ACCESS
7266 C724 MOVFF 0x724, 0x751
726A C71B MOVFF 0x71b, 0x750
726E 6B53 CLRF 0x53, BANKED
7270 0E64 MOVLW 0x64
7272 6F52 MOVWF 0x52, BANKED
7274 0100 MOVLB 0
7276 EC24 CALL 0x848, 0
727A BC18 BTFSC 0x18, 0x6, ACCESS
727C 8CF2 BSF 0xff2, 0x6, ACCESS
727E BE18 BTFSC 0x18, 0x7, ACCESS
7280 8EF2 BSF 0xff2, 0x7, ACCESS
7282 C002 MOVFF 0x2, 0x71e
7286 C001 MOVFF 0x1, 0x71d |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Sat Jan 26, 2008 2:51 am |
|
|
Try #define PRESET_SIZE 100L math optimization uses lowest storage size so #define PRESET_SIZE 100 maybe that is what is getting you the 8 bit result instead of the 16bits you want. |
|
|
Ttelmah Guest
|
|
Posted: Sat Jan 26, 2008 3:36 am |
|
|
The key is that you are casting the result, _after_ the arithmetic.
So the arithmetic is performed in the type of the two values. PresetNumber is an int (8bit), so is the constant. Hence int8 arithmetic is used, then the result converted to a long.
Three different ways to ensure things perform as you want:
Code: |
1)
presetAddr = (long)presetNumber * PRESET_SIZE;
2)
#define PRESET_SIZE (100L)
presetAddr = presetNumber * PRESET_SIZE;
3)
presetAddr = presetNumber * (long)PRESET_SIZE;
|
Each of these ensures that _one_ of the values used in the arithmetic is a long, _before_ the arithmetic is performed. Hence int16 arithmetic is used.
The behaviour here, is 'standard C' in this regard, except that on most C's, the default arithmetic type is int16.
Best Wishes |
|
|
SET
Joined: 15 Nov 2005 Posts: 161 Location: Glasgow, UK
|
|
Posted: Sat Jan 26, 2008 11:57 am |
|
|
C works this way so that if you want the effect of arithmetic truncation or rollover, then the compiler wont stop you.. by *telling* it that at least one of the operands is long (as in Ttelmah's examples) then the widening is done first. It's C's strength and weakness - you have to know what you need exactly and tell the compiler! |
|
|
|
|
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
|