0

In my program I need to always get closest integer value greater than the argument. For that I'm using C ceil() function. Problem is it always returns numbers I'm not expecting.

E.g.

double num = 1 / 25.0;   // num is correctly 0.04(some 0s)1
ceil(num);               // ceil returns 1018

Earlier in my program I'm calling srand(time(NULL)), so I thought maybe it has something to do with it and I commented it out, but it didn't help.

It also returns 1018 when I call the function like this ceil(0.040000001). It has this weird behavior even when I call the function with arguments from the documentation.

Example program

//#include <stdio.h>
//#include <stdlib.h>

int main() {

    //double var = 1 / 25.0;
    double num1 = ceil(1.6);    // returns 1023

    return 0;
}

1 Answers1

2

As pointed out in comments, ceil returns a double, but if you don't specify a prototype for a function, a compiler must assume that the function returns int and that the types of the arguments (after applying the default argument promotions) are the same as the types of the function parameters. When the actual function is called, since the type of the parameter is wrong (ceil expects a double but you passed it an int), the behavior is undefined.

On many modern systems, floating-point arguments and integer-valued arguments aren't even passed in the same registers. So it's likely in this case that ceil, looking for a double argument, found only whatever garbage happened to be in the register for floating-point arguments; and the caller, expecting an int return value, found only whatever garbage happened to be in the register for integer returns.

The compiler ought to warn you about calling unprototyped functions by default. Check warnings, you'll avoid such issues.

Community
  • 1
  • 1
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • 2
    On register-rich architectures such as x64, it's more likely that floating-point numbers and integers are passed in different registers, so `ceil` is looking in the wrong place for the parameter and gets whatever garbage happens to be in the floating-point register, and you're looking in the wrong place for the return value and get whatever garbage happens to be in the integer register. So there's not necessarily *any* correlation between the value returned and what you passed. – trent May 01 '17 at 15:41
  • @trentcl As the answer is community wiki, no need for a comment. You may edit and improve the answer. – chux - Reinstate Monica May 01 '17 at 15:58