Home > Software design >  Negative float values casting to unsigned int on Arm and intel
Negative float values casting to unsigned int on Arm and intel

Time:02-17

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
}
  •  Tags:  
  • c
  • Related