Examples: large-numbers wiggly-worms
The pre-condition is a logical formula. It should be written so that if we "evaluate" it, the resulting value will be either the Boolean True or False.
We use the word "routine" as a generic term for procedures and functions. As you know, a function is a routine that has no side effects, and returns a value to the caller. Functions, by this definition, do not alter the values of any global variables, files, or arguments. Whereas the sole purpose of a procedure is to have a side-effect.
The signature of a routine, in a well-designed programming language, says quite a bit in the sense of pre post conditions.
When you declare a formal parameter as a value parameter, you are saying that its value at the end of the routine is by itself of no significance, and the actual argument for it is unchanged. When you declare it as a var (or in-out) parameter, you are saying that the routine is expected to change its value as seen by the caller.
Procedures often alter global variables whose names are not passed in as actual arguments. The heading of a procedure as declarable in the typical programming language does not make clear which globals are accessed and/or modified. The specifications of such procedures should list all such variables, and describe their values before and after a call to the procedure. If the variable name is x, we can use x0, or old-x, to stand for the value it had immediately upon entry into the routine.
POST: (old-X[i] == HEX[X[i]], for 0 <= i <= n-1) && (X[i] == 0, for N <= i <= ND)
Frequently, we have a file that declares many globals. Not all of them are manipulated by a routine. So, adopt the following convention. If a post condition is silent regarding a global, we assume that it is actually asserting that that global is-Unchanged by that routine. Some time a routine may not only read but also actually update the value of global in between but finally leaves its value as it was upon entry. In this case, silence is unacceptable, and we should explicitly state that the global is unchanged.
Consider the following code:
int f (T x) {
int r;
if (! bexp(x))
return -1;
... more code ...
... r is defined so that r >= 0...
return r;
}
This is typical of many functions. Some checking of the given value of x is made. The function is checking its precondition in order to improve its robustness. If it does not pass this test, i.e., bexp(x) is false, the routine quits. This is often indicated to the caller by returning a value that is outside the "legit" values, in this example a -1. In other examples, you might see a panic() routine being called.
Q: Is bexp(x) a precondition of f() or not?
A: It is a precondition.
We list some predicates that we can think of as being predefined. These are useful in post conditions.
V is-defined
asserts that a legitimate value from the domain type of v has been assigned to the variable v after its declaration. V is-undefined is the same as not (V is-defined).V is-unchanged
asserts that the variable v is unchanged. That its value at the point of return is the same as it was at the point of entry.P is-malloc-returned
asserts that the pointer value stored in the variable p is a value returned by the routine malloc. You can create many other similar predicates by using the names of other functions in place of malloc.
May 6, 1998