Ravenous
Ravenous

Reputation: 356

"the C programming language" book exercise 1.2 possible wrong result

#include <stdio.h>
   /* print Fahrenheit-Celsius table
       for fahr = 0, 20, ..., 300 */
main()
   {
     int fahr, celsius;
     int lower, upper, step;
     lower = 0;
     upper = 300;
     step = 20;
     fahr = lower;
     while (fahr <= upper) {
         celsius = 5 * (fahr-32) / 9;
         printf("%d\t%d\n", fahr, celsius);
         fahr = fahr + step;
    } 
}

based on the above code I can't understand how you get the below result on the first line. Shouldn't it be 0 -17? This example is on page 17 of the C programming language. I just want to make sure this isn't something to do with older implementations of C, and I'm not getting the same result as the book because I'm using a more current compiler.

1    -17
20   -6
40   4
60   15
80   26
100  37
120  48
140  60
160  71
180  82
200  93
220  104
240  115
260  126
280  137
300  148

Upvotes: 3

Views: 358

Answers (2)

zwol
zwol

Reputation: 140826

Indeed, on the first time through the while loop, fahr has the value 0, and that is what will be printed. This is probably a typo in your edition of the book: we have multiple reports in the comments that other editions have 0 where yours has 1.

You are right to be concerned about old C code behaving differently with newer compilers. However, this program does not have any of the things in it that usually cause problems with newer compilers: no pointer aliasing, no concurrency, no arithmetic overflow, etc. The computation of the first two values of the celsius column does involve integer division with a negative dividend, which was partially implementation-defined prior to C1999; if the book had given -18 and -7 for those values, that would have been why. And modern compilers will issue a warning about the missing return type of main, but that doesn't affect the semantics of the program. (I'm not aware of any modern C compiler that actually issues an error for "implicit int", either in its default mode or in its "strictly conforming to C2011" mode. There's usually a way to tell it to make that particular warning into an error, of course.) None of these issues could have have caused the first value of fahr to be printed as 1.

Please learn from this that you should trust your ability to mentally simulate the execution of a program a little more, but printed books a little less. You would also be well-advised to get a newer C textbook—not just a newer edition of K&R, but an entirely new book, that covers the modern language. I regret to say I don't have any recommendations, though.

Upvotes: 4

Lundin
Lundin

Reputation: 214880

K&R was written when dinosaurs walked the earth. On pre-standard C and C90, the rounding direction of negative integer division was not well-defined. So you could get different results depending on compiler, it was implementation-defined behavior back in the days. I'm not sure if K&R were even aware of the issue - the book is filled to the brim with reliance on poorly-specified behavior.

This bug in the C language was not fixed until the year 1999, some 20 years after the book was written.


See What is the behavior of integer division?, the answer by schot in particular.

Also see the C99 rationale 6.5.5

In C89, division of integers involving negative operands could round upward or downward in an implementation-defined manner; the intent was to avoid incurring overhead in run-time code to check for special cases and enforce specific behavior. In Fortran, however, the result will always truncate toward zero, and the overhead seems to be acceptable to the numeric programming community. Therefore, C99 now requires similar behavior, which should facilitate porting of code from Fortran to C. The table in §7.20.6.2 of this document illustrates the required semantics.

Upvotes: 0

Related Questions