The problem I have is concerning practice problem (2.32 - pg.94) from Computer Systems: A Programmers Perspective third edition by Randal Bryant and David O'Hallaron.
The problem is as follows:
You are assigned the task of writing code for a function tsub_ok, with arguments
xandy, that will return 1 if computingx-ydoes not cause overflow. For what values ofxandywill this function give incorrect results?
The authors say that the function will give "correct values, except when y is TMin," but when I experiment with the value TMin for y it seems to work fine.
The tsub_ok function is as follows:
/* Determine whether arguments can be subtracted without overflow */
int tsub_ok(int x, int y)
{
return tadd_ok(x, -y);
}
The tadd_ok function is as follows:
/* Determine whether arguments can be added without overflow */
int tadd_ok(int x, int y)
{
int sum = x+y;
int neg_over = x < 0 && y < 0 && sum >= 0;
int pos_over = x >= 0 && y >= 0 && sum < 0;
return !neg_over && !pos_over;
}
Continuing on with the solution explained by the authors in regards to the functions, "we will have -y in the tsub_ok function in the tadd_ok function call also equal to TMin. So, the call to function tadd_ok will indicate overflow when x is negative and no overflow when x is nonnegative. In fact, the opposite is true: tsub_ok(x, TMin) should yield 0 when x is negative and 1 when it is nonnegative."
I tested these functions with a value of TMin for y, and negative and nonnegative values for x. The functions seem to work correctly for these values. The tadd_ok function indicates negative overflow when x is negative with the tsub_ok function returning 0. The tadd_ok function indicates no overflow when x is nonnegative with the tsub_ok function returning 1. Therefore, the functions seem to be working as intended even with TMin for y and negative and nonnegative values for x. So, I am confused how the results are incorrect.
Any help will be much appreciated thank you all in advance.
Consider the case when
intis 32-bit two’s complement,intarithmetic is defined to wrap modulo 232, andtsub_okis called withtsub_ok(-2147483648, -2147483648).Then
tsub_okcallstadd_ok(-2147483648, - -2147483648).- -2147483648wraps (2,147,483,648 is not representable inint; the maximum representable value is 2,147,483,647) to −2,147,483,648. Sotadd_okis effectively called withtadd_ok(-2147483648, -2147483648).Then
tadd_okcomputessum = -2147483648 + -2147483648, which wraps and setssumto 0.Then, in
int neg_over = x < 0 && y < 0 && sum >= 0;,xis less than zero,yis less than zero, andsumis greater than or equal to 0, soneg_overis set to 1.Then
return !neg_over && !pos_over;causestadd_okto return 0, andtsub_okreturns 0 too.However, this is an incorrect result. Subtracting −2,147,483,648 from −2,147,483,648 yields 0 with no overflow. A correctly working
tsub_okwould return 1, to indicate the subtraction is okay.Therefore
tsub_okis defective.