Integer multiplication, division

Started by
16 comments, last by Cornstalks 11 years, 6 months ago
Thank you for explaining the situation, this clears up my doubts. I am programming an application in AVR Studio 5.1 using gcc for an Atmega328p microcontroller. Due to limited RAM on a microcontroller (2 KB) I tend to stick to 8-bit and 16-bit variables. I did some tests and it seems that increasing at least one of the vars in the equation will produce the correct result.

This does not seem to work though.
int16_t result = (uint32_t)a * b / c; // does not work

I'll do some more tests.

Regards,
Bismuth
Advertisement

On a side note, C++ does enforce integer promotion in this situation, so the result in C++ will be as you expected.
And on yet another side note, even when I tried to reproduce your results with VS2010 compiling the code as C code, I still get -104 so it appears it does integer promotion like C++ requires even in C.

Actually, C has integer promotion rules as well (I'm pretty sure C++ got them from C in the first place). The only way that the result he's getting makes sense is if int on his compiler is 16-bits in which case manually casting to plain int isn't going to help either.

Thank you for explaining the situation, this clears up my doubts. I am programming an application in AVR Studio 5.1 using gcc for an Atmega328p microcontroller. Due to limited RAM on a microcontroller (2 KB) I tend to stick to 8-bit and 16-bit variables. I did some tests and it seems that increasing at least one of the vars in the equation will produce the correct result.

This does not seem to work though.
int16_t result = (uint32_t)a * b / c; // does not work

I'll do some more tests.

Regards,
Bismuth

Your variable a holds a negative value and you're casting it to an unsigned integer. Unsigned variables cannot hold negative values. And yes, it is technically enough to cast just a or b, because the other operands will be promoted automatically.


[quote name='Brother Bob' timestamp='1349813870' post='4988466']
On a side note, C++ does enforce integer promotion in this situation, so the result in C++ will be as you expected.
And on yet another side note, even when I tried to reproduce your results with VS2010 compiling the code as C code, I still get -104 so it appears it does integer promotion like C++ requires even in C.

Actually, C has integer promotion rules as well (I'm pretty sure C++ got them from C in the first place). The only way that the result he's getting makes sense is if int on his compiler is 16-bits in which case manually casting to plain int isn't going to help either.
[/quote]
I was reading through both the C and C++ specification (the drafts only, but I doubt these details change) and the two were different in that C++ explicitly mentioned integer promotion for narrow integers and C did not; otherwise the wording was more or less identical. I did not read much more than that into it, so you may very well be right.

Your variable a holds a negative value and you're casting it to an unsigned integer. Unsigned variables cannot hold negative values. And yes, it is technically enough to cast just a or b, because the other operands will be promoted automatically.

Eh, sorry it was a typo. I wonder why I typed uint anyway.

int16_t cc = (int32_t)aa * bb / (pe->fade_out); // This works.
To clarify this a little bit, the C standard says this about evaluating an integer expression:

If an [font=courier new,courier,monospace]int[font=arial,helvetica,sans-serif] [/font][/font]can represent all values of the original type, the value is converted to an [font=courier new,courier,monospace]int[/font]; otherwise, it is converted to an [font=courier new,courier,monospace]unsigned int[/font]. These are called the integer promotions. All other types are unchanged by the integer promotions.
[/quote]
If I'm understanding that right, on a 32-bit system (that is, when `int` is 32-bits), then yes, you'd get the right result of -104 because each operand is implicitly promoted to an `int`. But on a system where `int` is smaller than 32-bits, (like if `int` is 16-bits), then you'll have overflow. Which is exactly why you need to either use bigger datatypes or use that cast.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

To clarify this a little bit, the C standard says this about evaluating an integer expression:

If an [font=courier new,courier,monospace]int[font=arial,helvetica,sans-serif] [/font][/font]can represent all values of the original type, the value is converted to an [font=courier new,courier,monospace]int[/font]; otherwise, it is converted to an [font=courier new,courier,monospace]unsigned int[/font]. These are called the integer promotions. All other types are unchanged by the integer promotions.

If I'm understanding that right, on a 32-bit system (that is, when `int` is 32-bits), then yes, you'd get the right result of -104 because each operand is implicitly promoted to an `int`. But on a system where `int` is smaller than 32-bits, (like if `int` is 16-bits), then you'll have overflow. Which is exactly why you need to either use bigger datatypes or use that cast.
[/quote]

you live, you learn :)
Just use 32 bit integers, I dont really see why trying so hard to use 16 bits, is there a reason for it?

Just use 32 bit integers, I dont really see why trying so hard to use 16 bits, is there a reason for it?

The OP explained:

I am programming an application in AVR Studio 5.1 using gcc for an Atmega328p microcontroller. Due to limited RAM on a microcontroller (2 KB) I tend to stick to 8-bit and 16-bit variables.


Seems like a reasonable enough thing to do with limited memory.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

This topic is closed to new replies.

Advertisement