I am learning C++ by reading Stroustrup's "Principles and Practice Using C++".
In the section about pre- and post-conditions there is the following example of function:
int area(int length, int width)
// calculate area of a rectangle;
// pre-conditions: length and width are positive
// post-condition: returns a positive value that is the area
{
if (length<=0 || width <=0)
error("area() pre-condition");
int a = length*width;
if (a<=0)
error("area() post-condition");
return a;
}
What confused me is the task about this code:
Find a pair of values so that the pre-condition of this version of area holds, but the post-condition doesn’t.
Are there such possible values for integer that pre-conditions is ok but post-condition not?
Are there such possible values for integer that pre-conditions is ok but post-condition not?
Yes there's a number of input values, that can cause the post condition to fail. If e.g.
int a = length*width;
overflows the positive int
range (std::numeric_limits<int>::max()
) and the compiler implementation yields a negative value for this case.
As others noted in their answers, the situation that length*width
goes out of bounds from ]0-std::numeric_limits<int>::max()[
is actually undefined behavior, and the post condition renders merely useless, because any value might need to be expected for a
.
The key point to fix this, is given in @Deduplicator's answer, the pre-condition needs to be improved.
As a lance for Bjarne Stroustrup's reasonings to give that example:
I assume he wanted to point out that such undefined behavior might lead to unexpected negative values in the post-condition and surprising results for a naive assumption checked with the pre-condition.
No, there aren't any values that will, within the bounds of defined behavior of standard C++, violate the post-condition. However, there are values that still can make the function behave incorrectly, namely values so large that their product does not fit within an integer. Try passing 200'000 and 15'000.
Due to the way most compilers implement C++, you might see the post-condition being violated, but what you're actually observing is undefined behavior due to integer overflow.
The answer is that his precondition-check is incomplete. Even though it is too restrictive.
He failed to include a check that the product can be represented instead of resulting in UB:
int area(int length, int width) {
// calculate area of a rectangle
assert(length >= 0 && width >= 0 && (!width
|| std::numeric_limits<int>::max() / width >= length));
int a = length * width;
assert(a >= 0); // Not strictly neccessary - the math is easy enough
return a;
}
What comes to my mind is a signed overflow. It is undefined behavior but might yield a negative value.
Try std::numeric_limits<int>::max()
and 2
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With