I am facing the below which is when I run below code
int main()
{
float test = -6.25f;
unsigned int result_1;
result_1= (unsigned int)test ;
printf("test result_1: %x \n", result_1);
return 0;
}
The output on arm is equal 0 and output on intel is equal 4294967291 .
Do you know how can force intel compiler to make output 0 as arm compiler?
CodePudding user response:
From https://en.cppreference.com/w/c/language/conversion :
Real floating-integer conversions
A finite value of any real floating type can be implicitly converted to any integer type. Except where covered by boolean conversion above, the rules are:
The fractional part is discarded (truncated towards zero).
- If the resulting value can be represented by the target type, that value is used
- otherwise, the behavior is undefined
Your code does:
float test = -6.25f;
(unsigned int)test;
The type unsigned int
is not able to represent the value -6
. You can't convert a float
with a negative value to unsigned
type. Your code has undefined behavior.
Do you know how can force intel compiler to make output 0 as arm compiler?
Check if the value is less than 0.
int result_1 = test < 0 ? 0 : <something else here>;
If your compiler if following ANNEX F addition to the C language, then according to https://port70.net/~nsz/c/c11/n1570.html#F.4
[...] if the integral part of the floating value exceeds the range of the integer type, then the ''invalid'' floating- point exception is raised and the resulting value is unspecified [...]
In which case anyway, the resulting value is unspecified, so it may differ between compilers as you experience.
CodePudding user response:
When converting an float
to unsigned
, code is subject to:
When a finite value of real floating type is converted to an integer type other than
_Bool
, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined.) C17dr § 6.3.1.4 1
To avoid undefined behavior (UB) for that conversion for out-of-range values, code needs to test the float
value first. The typical valid range for conversion is -0.999... to 4,294,967,295.999...
#define UINT_MAX_PLUS1_FLT ((UINT_MAX/2 1)*2.0f)
unsigned float_to_unsigned(float f) {
// Exclude values that are too small, too big or NAN
if (f > -1.0f && f < UINT_MAX_PLUS1_FLT) {
return (unsigned) f;
}
return 0; // Adjust as desired
}