Search code examples
cfunctiontype-conversionundefined-behavior

Why does conversion from int to float not take place when we pass 'int' to a function expecting float in C?


I wrote a simple program below which calculates the sum and return the result to main(). The main() then calculates the average. SumOfArray() expects float but I am passing an array of integers. I expected that the integers would be converted into float type implicitly. i.e 35 would be passed as 35.0 but to my surprise it was 0. the short explanation from whatever I could find is that the behavior is undefined because in this case the typecast happened not from (int)->(float) but (int*)->(float*)

However why does the function SumOfArray() see 0 instead of actual integers if it is reading from the same location. I checked this by printing the address of array both in main() and SumOfArray(). They were same. Is there anything specific about this mentioned in ISO C standards? The size of integer and float on my machine is 4 bytes so I expected it would read same values albeit with loss of precision.
Following is my program. I printed the values of array passed to the function in SumOfArray. I am using gcc compiler , codeblock ide compiling for x86_64. Tried this on debian as well.

#include<stdio.h>

float SumOfArray(const float array[],unsigned int size)
{
  float sum=-1.0;
  if(size!=0&&array!=0)
  {
    sum=0;
    for(int i=0;i<size;i++)
    {
      sum+=array[i];
      printf("sum in sum of array is%f\n",sum);
      printf("array[%d] is %f\n",i,array[i]);
    }
  }
  return sum;
}

int main()
{
  int gradesI[]={35,56,88,23,45,99};
  unsigned int sizeI = sizeof(gradesI)/sizeof(int);
  
  float sumI = SumOfArray(gradesI,sizeI);
  printf("the sum of is %f\n",sumI);
  
  float average = sumI/sizeI;
  printf("the average is %f\n",average);
  
  return 0;
}

- *output*
sum in SumOfArray is 0.000000
**array[0] is 0.000000**
sum in SumOfArray is 0.000000
**array[1] is 0.000000**
sum in SumOfArray is 0.000000
**array[2] is 0.000000**
sum in SumOfArray is 0.000000
**array[3] is 0.000000**
sum in SumOfArray is 0.000000
**array[4] is 0.000000**
sum in SumOfArray is 0.000000
**array[5] is 0.000000**
the sum of is 0.000000
the average is 0.000000

Solution

  • You are not passing a int but a pointer to int (decayed from a array of int) and you don't expect a float but a pointer to float.

    What you have in memory gradesI:

    +------+------+------+------+-
    | int  | int  | int  | int  | ...
    +------+------+------+------+-
    

    When you call a function with gradesI as argument, it decays to a pointer to int, a pointer that points to gradesI[0].

    What SumOfArray() expects the pointer pointing to in memory

    +------+------+------+------+-
    | float| float| float| float| ...
    +------+------+------+------+-
    

    What you ask is why the int array isn't converted automatically to a float array. There are multiple reasons:

    • In c only the argument itself (i.e. the pointer) gets converted. A pointer to int shouldn't be implicitly converted to a pointer to float, because you can't access a int through a float pointer (when you try it you get undefined behaviour).

    • The compiler would have to generate a new temporary array and passing a pointer to the new temporary array. But that would break a lot of code since we expect the pointer in the function to point to the same location as in the caller.

    • The compiler doesn't know how many int's it should convert to float.

    • Even if the compiler knows that, it would be time consuming.