Harsha Harsha - 8 months ago 55
C Question

I'm getting warning "floating point overflow "


short int b = (short int)(((-100) * (1UL << 6)) - 0.5);
short int c = (short int)( (-6400) - 0.5 );

printf("%d",sizeof(short int));

output :

b : 32767

c : -6400

Why I'm getting different results?
Is this because of type conversion?

Since I cant put the exact copy of code here, I wrote the part that showing up the warning in the Codepad and pasted it here.
I'm using Posek compiler.
The above expression is used in one of the configuration. When I run the code in Trace32, I came to know that it has acquired the value "-1". I'm not getting how the value "-1" came ?

Compiler is displaying :

warning : floating point overflow

Answer Source

Your issue is here:

(-100) * (1UL << 6)

Multiplication performs the usual arithmetic conversions on its operands and then the integer promotions for this case and that caused -100 to be converted to unsigned long which means it will have a very large unsigned value which does not fit into signed short. This is singed integer overflow which is undefined behavior.

The fix would be as follows:

(-100) * (1 << 6)

Note that sizeof does not return an int the correct format specifier for printf would be %zu.

Turning up the warnings on your compiler really helps, using clang and the following flags -std=c99 -Wall -Wextra -Wconversion -pedantic I received the following warnings:

warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion]
short int b = (short int)(((-100) * (1UL << 6)) - 0.5);
                            ^~~~  ~

warning: format specifies type 'int' but the argument has type 'unsigned long' [-Wformat]
printf("%d",sizeof(short int));
        ~~  ^~~~~~~~~~~~~~~~~

For reference the draft C99 standard section 6.5.5 Multiplicative operators says:

The usual arithmetic conversions are performed on the operands.

and section Usual arithmetic conversions says:

Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands:

and for this, the following applies since -100 will be int and the other operand is unsigned long:

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.