When the first edition of K&R was written, there was no C standard. When the second edition of K&R was written, the C89/C90 standard was about to be finalized. Because of the legacy from code written before C89 was finalized, the standard had to permit:
#include <stdio.h>
double sqrt();
main(argc, argv)
char **argv;
{
if (argc > 1)
printf("sqrt(%s) = %f\n", argv[1], sqrt((double)atoi(argv[1])));
else
printf("sqrt(%.0f) = %f\n", 2.0, sqrt(2.0));
return 0;
}
Note that the return type of main() is implicitly int; the function argument argc is implicitly int; the function atoi() has an implicit return type of int. Note too that the argument to sqrt() had to be explicitly a double value; the compiler could not automatically convert the argument type because prototypes were not a part of C before the C89 standard.
Such code is no longer acceptable to C99 or C11 compilers. You could use:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc > 1)
printf("sqrt(%s) = %f\n", argv[1], sqrt(atoi(argv[1])));
else
printf("sqrt(%.0f) = %f\n", 2.0, sqrt(2));
return 0;
}
This uses the standard headers to declare the functions with complete prototypes, so it is no longer necessary to cast the argument to sqrt(). In C99 or C11, you could omit the return 0; and the effect would be the same. Personally, I don't like the loophole that allows that and continue to write the return explicitly. The return was necessary in C90 to send a determinate status to the environment (e.g. the shell the invoked the program).