Rod said:
Okay, we're on the same page here.
Other than just saying "it's a constraint violation", do you understand why
you _can't_ do this? ...
No. I understand why an implemention could in fact do this. However,
in most cases it's horribly inefficient, and the standard was
therefore explicitly written to not mandate such inefficiency.
... If a byte is the minimum addressable unit of storage,
The C byte is the minimum unit of storage that can be addressed by C
code. It need not be the same as the hardware addressable unit, and
there are many implementations where it is much smaller.
and all non-bitfield objects are aligned on byte boundaries, how do you
construct a pointer to point in-between bytes? to some un-addressable bit?
By creating a pointer that consists of a byte address and a bit
offset. Much the same approach must already be used to emulate char*
pointers on machines where the addressable storage unit was deemed, by
the implementor, to be too large for use as a C byte. The issue isn't
whether it's feasible for an implementation to provide bit-pointers;
it certainly is feasible. The issue is whether the C standard mandates
them; and it very specifically excludes the possibility.
That's exactly what we've been discussing. 6.3.2.3p7 says the pointer
conversion from a type resulting in the same type is loss-less and it's
usage, if misaligned, is undefined.
If byte-alignment were the only thing it was talking to, how could the
pointer ever get misaligned? Misaligned C pointers is a meaningful
concept only in the context of alignment requirements larger than 1
byte.
It's not? How does a pointer point to an object then...
By identifying the location that the object starts at. This location
might be a word boundary, with (for example) 4 bytes to a word.
Pointers of that type might be incapable of pointing at positions
withing a word. This is all allowed by the C standard. char* and void*
can't have this characteristic, but long* and double* might, and
there's real machines on which they do.
... If it's not, then
no pointer can point to any object.
No such conclusion can be validly drawn from my assertion.
... Is that what you're claiming?
Not at all.
Really - not at all.
It [6.3.2.3p7] is referring to
alignment in the more general sense defined in 3.2p1: "requirement that
objects of a particular type be located on storage boundaries with
addresses that are particular multiples of a byte address".
Except for the fact that one specifies bit-fields as excluded for obvious
reasons and the other fails to do so, there is no difference between
6.3.2.3p7 and 3.2p1.
Yes there is. 3.2p1 defines what alignment means. 6.3.2.3p7 says,
among other things, that the behavior is undefined if you attempt to
convert a misaligned pointer. I see that as a rather huge difference,
my self.
True. But, all types, except bitfields, must be byte aligned.
Certainly, and irrelevant to 6.3.2.3p7.
They are
aligned to a byte boundary. If an int has a size of 4 and is aligned, it's
byte aligned to a byte boundary, every fourth byte...
Elsewhere, you seem to be implying that the only relevant alignment
requirement is 1 byte. However, in the above sentence it seems as
though you might be thinking that the alignment requirement has to
match the size. Is that what you're saying? if so, that's not the
case. A 4-byte int could have an alignment requirement of 2. What can
be proven by combining C's rules for pointer arithmetic, arrays, and
sizeof, is that the size of a data type must be an integer multiple of
the alignment requirement. The ratio of the size to the alignment
requirement could be 1, but is not required to be.
... but are still aligned on a byte boundary. A byte is the minimum
addresable unit. You can't point a pointer in-between a byte.
True, but the question is not whether you can point a pointer between
bytes. Let's consider an implementation where int is 4 bytes and has
an alignment requirement of 2. What 6.3.2.3p7 is saying is that the
following code:
int array[4];
int *pi = (int*)(1+(char*)array);
has undefined behavior, because the pointer value 1+(char*)array
points at an address which is incorrectly aligned to hold an int.
True. But, this has nothing to do with the issue.
That's not what 6.3.2.3p7 says. It says the pointer behavior for the
pointed-to type is undefined. It says nothing about the pointer conversion
being undefined.
"A pointer to an object or incomplete type may be converted to a
pointer to a different
object or incomplete type. If the resulting pointer is not correctly
aligned57) for the
pointed-to type, the behavior is undefined."
In the above sentence "the behavior is undefined" can only refer to
the behavior when such a pointer is "converted to a pointer to a
different type or incomplete type". Not the behavior after the
conversion, but the behavior of the conversion itself.
This is not just a pedantic debate about what the standard means; in
the real world there are systems where pointers to different types are
handled in different fashions. For instance, there may be
implementations with CHAR_BIT==8 on systems where the hardward
addressable unit (word) is 32 bits. On such systems, pointers to some
types that have a size which is a multiple of the word size may
identify only which word the object starts in, and be physically
incapable of representing positions that are not at the beginning of
word. 6.3.2.3p7 was written for the explicit purpose of allowing such
implementations to qualify as conforming to the standard.