K
Keith Thompson
CBFalconer said:For example, imagine a system where, after writing 0 to ioport 5,
memory addresses 1000 to 2000 address memory on one chip. After
writing 1 to ioport 5, those addresses reach another chip. There
is NO way to define greater or smaller addresses between the
chips. Yet pointers have to be able to access both!
Suppose malloc() is able to allocate memory at address 1500. So I
call malloc(), store the resulting pointer value in a variable, and
store a value at that location:
int *ptr = malloc(sizeof *ptr);
/* assume this gives me addrss 1500 */
*ptr = 42;
After writing to ioport 5, I still need to be able
to dereference that pointer and get back the data I wrote:
/* ... */
printf("%d\n", *ptr); /* This has better print "42" */
Possible solutions, in a conforming implementation, are:
No code with defined behavior (i.e., behavior defined by the standard)
can yield an address in that range, so the behavior of those addresses
is irrelevant.
Writing to ioport 5 invokes undefined behavior, so once you've done
that, all bets are off.
The C implementation's pointer format includes the identity of the
appropriate memory chip. Before deferencing such a pointer, the
compiler must either prove that the appropriate chip is active, or
generate code to write to ioport 5 first.
In the first two cases, the fact that the pointers can't be ordered is
irrelevant; in the last case, the extra information can be used to
define a (perhaps arbitrary) total ordering.
So there can't be a portable method of ordering pointers. Maybe
C++ has some sort of provision that excludes such a mechanism. C
doesn't, to my knowledge.
No, there's no *portable* method of defining a total ordering on
pointer values. C doesn't require implementations to define or use a
non-portable method of doing so.
<OT>
C++, with its std::less, does impose such a requirement; the "<"
operator needn't impose a total ordering (which avoids imposing extra
work where it's not necessary), but std::less must do so. As for
offsetof, the implementation can use whatever non-portable tricks it
likes to implement this.
</OT>