Variable sizes in if statement

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've got the following code:

            bool test_val(int a, unsigned char b)
            {
                const int MAX_VALUE = 32767;
                if(a*b>MAX_VALUE)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }

It's testing to see if result of the multiplication is greater than the possible value for an int.  So should I cast a to being a long, so it's able to work out the result of a multiplication > 32767.  Or does the compiler realise this and do this automatically?

Paul

This topic has a solution.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The compiler is not that clever.

Paul

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If a*b overflows a (16 bit) int, that's YOUR problem!

 

no run-time checking in microprocessor-land!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

stevech wrote:

If a*b overflows a (16 bit) int, that's YOUR problem!

 

no run-time checking in microprocessor-land!

Is it the fault of the microprocessor?  I'm guessing it will notice and set a bit in the status register.  So I would say there is no checking in C/C++ land.   But I could be wrong.

 

I don't see a bit in the status reg. called overflow, but there is a Carry bit.  Maybe checking this would do the trick.

Last Edited: Sun. Jun 28, 2015 - 05:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

steve17 wrote:
stevech wrote:

 

If a*b overflows a (16 bit) int, that's YOUR problem!

 

no run-time checking in microprocessor-land!

 

Is it the fault of the microprocessor?  I'm guessing it will notice and set a bit in the status register.  So I would say there is no checking in C/C++ land.   But I could be wrong.

AVRs do 8x8 to 16 multiplications.

They do not overflow.

The compiler has to build other combinations out of them.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Only some AVRs  have 8x8 hardware multiply, right?

 

I was referring to 8 x 16 (compiler/library converts to 16 x 16 no doubt). Overflow can be detected but C libraries don't do so. signed vs. unsigned are different stories.

Last Edited: Mon. Jun 29, 2015 - 06:56 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

C don't know anything about overflow! (before anyone kill me: the float lib do)

It's 100% your problem to make sure that it doesn't happen, or it doesn't matter if it happen (often you use overflow as a part of the solution). 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
C don't know anything about overflow! (before anyone kill me: the float lib do)

It's 100% your problem to make sure that it doesn't happen, or it doesn't matter if it happen (often you use overflow as a part of the solution).

Unsigned arithmetic does not overflow by definition.

Conversion to unsigned integers does not overflow by definition.

Where possible, conversion to signed integer is required to be value-preserving.

Other conversions to signed integer are implementation-defined and may generate traps.

Overflow in other signed arithmetic is undefined, the realm of nasal demons.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe the C/C++ compiler could generate a warning when 2 ints are multiplied and the result is stored in the same size int.  If you don't want the warning, you could cast the result to the undersized int.  I'm surprised C++ doesn't do this.  It warns about damned near everything else.,

 

Runtime checks could be made, but then you have to decide what to do if the check finds an overflow.  I think Microsoft's C++ compiler has a template for this.  It may throws an exception, but I've never used them and don't have an urge to do so. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Of course ANY arithmetic can have overflows. It is just that computer languages expect the punter to avoid them.
Yes, I am sure that you could create exceptions.
Regarding the original subject. The C language knows the sizeof int and char. You are responsible for ensuring that a×b is valid. Either cast to long or impose limits on the values of a and b.
In practice, sensors in an embedded system often have real life range limits. Just test for the outermost cases.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

steve17 wrote:
Maybe the C/C++ compiler could generate a warning when 2 ints are multiplied and the result is stored in the same size int.
The result is always stored in the same size int.

That is part of the language definition.

For the most part, casting an operand to the desired type is sufficient.

 

The possible exceptions I can think of involve floating point targets or operands.

I've not heard of an occurence.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

An AVR integer is usually 16-bits and its range is -32768 to 32767.  Unsigned char size is 0-255.  The range of int * unsigned char is -8,355,840 to 8,355,535.  Use a 32-bit long inside the function for the multiplication result and then compare your MAX_VALUE to this long.  The long variable will disappear when you leave the function.

 

  You don't need to create a const int variable for your MAX_VALUE.  Use a #define statement instead: #define MAX_VALUE 32767.   That's what a all-caps label usually means.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Use the types defined in <stdint.h>, and the macros contained therein:

 

            bool test_val(int16 a, uint8_t b)
            {
                if((int32_t)a*b>INT16_MAX)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:

Use the types defined in <stdint.h>, and the macros contained therein:

 

            bool test_val(int16 a, uint8_t b)
            {
                if((int32_t)a*b>INT16_MAX)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }

 

Umm--what about "underflow"?  I.e., a negative result less than -32k?

 

(As already mentioned above, I try to think about max values when writing the code in the first place, and if an overflow possible limit the input factors or detect a "fault" as appropriate.  For example, an AVR8 ADC result is 10 bits.  So a scaling equation can have a multiplier as high as 64 before an [unsigned] overflow.)

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

Umm--what about "underflow"?


Indeed. I was only addressing the issue of >>how<< to test for an ***erflow condition, and based my example on the OP's code.

I can't do >>all<< of the work for them ;)

In practice, I do the same as you and arrange that the operands never lead to an ***erflow condition, either by virue of real-world limits (ADC) or by testing operands >>before<< the at-risk expression.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Tue. Jun 30, 2015 - 04:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And sometimes it's so complex that you have to try all combinations. I remember when I made (just for fun) the U16 to BCD (in less than 70 clk), I checked if it was correct for all values, I cheated with some carry's that the product sum should have, and some (not all :) was needed).

 

It took the the PC about 1/2 hour to run all combinations, with my code, and a normal slow routine.