after all, we typically have to state what a function returns; that is, if we return a value from a function we are always making a promise about the return value (how else would a caller what to expect).
int area(int lenght, int width)
// pre-conditions : lenght and width are positive
// post-condition : returns a positive value that is the area
{
if (lenght <= 0 || width <= 0) error("area() pre-condition");
int a = lenght * width;
if (a <= 0) error("area() post-condition");
return a;
}
This is a simple example of using pre-condition and post-condition, but what I can not understand is what the author says after showing the example:
"We couldn't check the complete post-condition, but we checked the part that said that it should be positive".
What does it mean ? Why we couldn't check the complete post-condition ? In my understanding in this case as post-condition we just need to check that the variable a is positive, am I wrong ?
Than the author ask me this question :
Find a pair of value so that the pre-condition of this version of area holds, but the post-condition doesn't.
Is it not impossible ??
In my understanding in this case as post-condition we just need to check that the variable a is positive, am I wrong ?
Yes. Note the full post-condition...
returns a positive value that is the area
It's possible to pass values of length and width such that a does not come out to the correct area due to overflow.
Why we couldn't check the complete post-condition ?
Because part of the post-condition is "that is the area". We haven't checked that; and it's not trivial to check that the result of the multiplication is equal to the mathematically expected value.
Is it not impossible ??
If the multiplication overflows, giving undefined behaviour, then you might get a negative result from two positive inputs.
Your example is most certainly about the signed arithmetic overflow in lenght * width.
In this case this is a very bad illustration of the notion of post-condition. The expectation that should be delineated to explain pre-conditions is:
If the function is called with arguments that satisfy the pre-condition, then it does not invoke undefined behavior.
If the function is called with arguments that satisfy the pre-condition, then the post-condition holds when the function terminates.
The example in your question illustrates the first point, not the second one.
The author thinks that the function returns a negative “area” for some input, but the author is wrong: the function can only return the correct result (a positive value that is the correct area) or invoke undefined behavior. That this undefined behavior can lead to a appearing negative on some compilation platforms is irrelevant. Undefined behavior is forbidden. Undefined behavior is unpredictable.
Related
I am reading Bjarne Stroustrup's Programming: Principles and Practice Using C++ 2nd Edition, and he asks how could the post-condition for the function below fail after the pre-condition succeeded.
I guess technically, it doesn't have to return a negative area but so long as the post-condition fails while the pre-condition holds.
This is the last "Try This" from Chapter 5 about errors.
Is there such a pair?
int area(int length, int width)
// calculate area of rectangle
// pre-conditions: length and width are positive
// post-condtion: 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;
}
If the result of length * width is larger than what fits in an int, then you get signed integer overflow. Normally one would assume that the result is negative if that happens. However, signed integer overflow is actually undefined behavior (UB), so it's not guaranteed that the result is negative. Or, even if it is, it's not guaranteed that a <= 0 will actually be true so error() might not get called because the compiler could assume that a can never be negative. The compiler is free to eliminate branches that could only be reached through UB.
This is unfortunately the nature of UB.
Is it possible to do the following without getting a stackoverflow?
int foo(int i = 0)
{
return foo(--i) || i;
}
When foo(--i) evaluates to 0, it should return false, therefore returning i and ending the execution.
You want return !i || foo(--i).
Note that || is short-circutted. This means that evaluation (which is performed from left to right) will continue for only as long as the result of the expression is not known. So the way I've written it, the case i being zero will block the recursion.
(Moving on to more advanced issues, you need to be very careful when evaluating expressions when the same variable appears in more than one sub-expression and it's value is changed in some of them. My having !i and --i could get me in trouble: I'm not too far away from undefined behaviour here. In fact, it turns out that my code is completely safe since || is a sequence point and the order of evaluation with || is well-defined. But do be careful.)
From what you have coded foo never returns because it will continuosly go on decreasing i and recurse. You need a check inside foo which returns whatever you want when you get i as 0.
I have this class which has a private bool member variable call positive. I want to check to see if both my class and the number I am adding to it are both positive so I wrote the expression
positive == (n > 0) //n is of type int
But for some reason when both are positive this evaluates to false. I then did a cout on positive and it has a value of 204! I though a boolean only holds 1 or 0. That would be why this is evaluating to false but why is that and how do I fix it? I am using Visual Studio 2013.
Just to clarify it should be == because I want to know if the sign is the same. So I want it to be true if both are negative or both are positive. I think I solved the problem which was that positive in one particular test case wasn't being initialized. But still why would a bool variable even if uninitialized contain a value larger and 1?
As per the standard, getting the value of an uninitialized variable is undefined behavior.
Since the actual size of a bool can be more than one bit, a bool variable containing rubbish can even hold bad values like 254. Welcome in the C++ hell!
And since (n > 0) evaluates to 1, 254 == 1 is false.
The bug is most likely due to the fact that positive never got a meaningful value since the object that contains it come into existence.
Search for a positive = something into your code and see if it is executed at least once before you use it.
Edited after Konrad comment:
The problem is most likely due to the fact that == is implemented between int-s and not bool-s relying on a bool-to-int promotion assuming the implementation of bool use 0 for false and 1 for true (and since && and || between int-s assume 0 for false and non-zero for true, bool-to-int promotion can be an identity).
This can be seen as a "compiler unfairness", but -since in the space of integer there is one false and bilions of trues- if operator==(bool,bool) was applied, there where more chance the uninitialized bug wold have been not discovered.
Treating bool as int in the arithmetic operations (not logic ones) makes bad-bool values to come out, thus revealing the bug.
Of course, since behind it there is an UB, it's all in an implementation choice. And it is int the freedom of each reading this to think I'm try to sell a bug as a feature.
Oh, you have a == where you should have an =.
The == doesn't assign, it checks for equality
Should be
bool positive = (n > 0) //n is of type int
bool generally holds only 1 or 0 after assignment. The only reason I can imagine you would see 204 in a bool is if the variable was uninitialized (so it had a junk value).
What if I have something like this:
int a = 20;
int min = INT_MIN;
if(-a - min)
//do something
Assume that INT_MIN if positive is more than INT_MAX. Would min ever be converted by the compiler to something like -min as in -INT_MIN, which could be undefined?
You are right that unary minus applied to INT_MIN can be undefined, but this does not happen in your example.
-a - min is parsed as (-a) - min. Variable min is only involved in binary subtraction, and the first operand only needs to be strictly negative for the result to be defined.
If the compiler transforms the subtraction to something else, it is its responsibility to ensure that the new version always computes the same thing as the old version.
The result of x - y is defined as the mathematical result of subtracting y from x. If the mathematical result can be represented in the result type (int in this case), then there is no overflow.
A compiler is free to transform the expression in any way it likes, such as by changing
x - y
to
x + (-y)
but only if the transformation keeps the same behavior in cases where the original behavior is well defined. In the case of y == INT_MIN, it can still perform the transformation as long as the undefined behavior of evaluating -INT_MIN yields the same end result (which it typically will).
To answer the question in the title:
Is INT_MIN subtracted from any integer considered undefined behavior?
INT_MIN - INT_MIN == 0, and cannot overflow.
Incidentally, I think you mean int rather than "integer". int is just one of several integer types.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
Undefined Behavior and Sequence Points
Ok we all know that i++ increments value by 1 on next line and ++i increments on same line(please correct me if i am wrong there ) so for a sample statement of c as follows:
int a=0;
printf("%d , %d",++a,a);
the expected output should be 1 , 1 but instead it gives 1 , 0
so as one might guess what i am asking here is why does the second linking of
i print 0 instead of 1 when the value is already incremented.
So if post increment didn't increment value in the same line then what is the
difference between post and pre increment? edit : changed the name of variable from i to a to avoid grammatical confusion.
You are very wrong in your understanding of the increment operators.
i++ increments i, and returns its old value; ++i increments i,
and returns the new value. When the actual incrementation takes place
is only guaranteed to be after the preceding sequence point, and before
the next; in your code, this means before the call to printf.
Beyond that (and largely because of that), if you modify the value of an
object, you're not allowed to access it anywhere else without an
intervening sequence point, except as needed to determine the new value.
You violate this rule, so your code has undefined behavior.
It's undefined behavior. the compiler is allowed to calculate the parameters in any order. your compiler just calculate it from right to left, so the rightest parameter is 0, and the 2nd is 1.
edit: as Seth said, the compiler is only free to change the order of calculating, not to do whatever it wants, so when you don't care about the order you can freely call functions, but you should never assume that one parameter is been calculated before another.
I think your question is not about how increment work. The phenomenon you have observed is about the order of passing parameter to a function. As far as I can remember, this is not defined by c++ standard, so it's a UNDEFINED BEHAVIOR. Meaning different compiler could have different implementation.
E.g.
One compiler could pass parameter from left to right, then a different could pass parameters from right to left.
You can have a better read of Sequence point here:
http://en.wikipedia.org/wiki/Sequence_point
printf("%d , %d",++i,i);
is undefined behavior.
Your are violating C sequence points rule:
(C99, 6.5p2) "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored."
Once I read in some book that when a statement is like this:
printf("%d , %d",++a,a);
The execution starts from right to left but outputted as left to right. Therefore you see the out as 1 0 - 'a' is calculated first = 0 then '++a' = 1, but displayed as 1 0
This is strange but yeah that's how it works.
Hope this helps.