Defect Report #172

Submission Date: 16 Oct 95
Submittor: BSI
Source: Clive D.W. Feather
Question
Submitted to BSI by Clive D.W. Feather [email protected] .
In this Defect Report, identifiers lexically identical to those declared in standard headers refer to the identifiers declared in those standard headers, whether or not the header is explicitly mentioned.
This Defect Report has been prepared with considerable help from Mark Brader, Jutta Degener, Ronald Guilmette, and a person whose employment conditions require anonymity. However, except where stated, opinions expressed or implied should not be assumed to be those of any person other than myself.
Defect Report UK 020: Relational and equality operators
The descriptions of these operators with pointer operands contain several defects.
Part 1
Consider the following code:
char *s = "a string";
if (s = NULL)
/*
... */

Subclause 6.3.8, Semantics reads in part:
If the objects pointed to are not members of the same aggregate or union object, the result is undefined
This implies that the comparison causes undefined behavior.
Subclause 6.2.2.1 reads in part:
Such a pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
This implies that the comparison is guaranteed to yield false.
This is a direct contradiction.
Part 2
Subclause 6.3.9, Semantics reads in part:
Where the operands have types and values suitable for the relational operators, the semantics detailed in subclause 6.3.8 apply.
This can reasonably be read as meaning that, whenever the constraints of subclause 6.3.8 apply, its definitions should be used, even if that would result in undefined behavior. (The phrase and values can reasonably be read as requiring only that the pointers both be to objects; it does not necessarily mean that the result of the comparison must be defined.)
It further reads:
If two pointers to object or incomplete types are both null pointers, they compare equal. If two pointers to object or incomplete types compare equal, they both are null pointers, or both point to the same object, or both point one past the last element of the same array object.
This says nothing about the comparison of any other pointers. Now, subclause 3.16 reads in part:
Undefined behavior is otherwise indicated ... by the omission of any explicit definition of behavior.
Thus, in:
int a, b;
&a == &b

the comparison causes undefined behavior!
Part 3
The above citation does not allow for the case where one pointer is to an object, and the other is one past the last element of an array object. If an implementation places two independent objects in adjacent memory locations, a pointer to one would equal a pointer to just past the other on many common implementations.
If these pointers are not to be viewed as identical, then the wording is defective.
Suggested Technical Corrigendum
In subclause 6.2.2.1, replace the cited text by:
Such a pointer is called a null pointer.
In subclause 6.3.9, replace the first paragraph of the semantics by:
The operators == (equal to) and != (not equal to) shall yield 1 if the specified relation is true and 0 if it is false. If the operands have types suitable for those of a relational operator and values that would not cause undefined behavior if used with a relational operator, then the result of the comparison, either greater than or less than (both implying not equal to) or equal to, is the same as with a relational operator.
Insert at the start of the second paragraph:
Otherwise the operands are pointers, and they shall compare either equal or not equal.
If part 3 is viewed as an issue, then in the same paragraph change:
or both point one past the last element of the same array object.
to:
both point one past the last element of the same array object, or one points one past the last element of some array object and the other points to the first element of a different array object.
Response
This is a work in progress item.
Summary of Part 1:
The standard does not currently state what happens with relational operators when you compare the address of an object with a null pointer.
We know from the citation from subclause 6.2.2.3 that a null pointer is guaranteed to yield false when compared with a pointer to an object.
It is explicitly undefined behaviour to use relational operators on two pointer that are not members of the same aggregate or union object. However it is unstated whether a null pointer compares greater or less than the address of an object and hence is implicitly undefined behaviour.
Is this the desired behaviour?
Note: the current C++ clause has the following wording:
If two pointers of the same type point to different objects or functions, or only one of them is null, they compare unequal.

This wording gives the possibility for C and C++ to give different results.
Summary of Part 2:
Discussion from Nashua is as follows:
The intent is that pointers to distinct object will compare unequal, The C Standard will be fixed in a future revision. Previous Defect Report < - > Next Defect Report