Keith Thompson said:
James Kuyper said:
Actually, that's precisely what double[2] is; and
_Alignof(double[2]) probably would be 16 on such a platform.
N1570 6.5.3.4p3:
The _Alignof operator yields the alignment requirement of its
operand type. The operand is not evaluated and the result is
an integer constant. When applied to an array type, the result
is the alignment requirement of the element type.
Ah - that's new, I think - I haven't had time to fully digest the
changes made in C2011. In principle the same requirement could have
been worded in earlier versions of the standard in terms of the
alignment of the type without mentioning _Alignof(), but I don't
think that it was. Am I correct?
Search for every occurrence of "alignment" in N1256, I see no
explicit statement about the alignment of array types (which is a
bit surprising).
But I think the *required* alignment for an array type was already
the same as the required alignment for the element type.
For example, I *think* this program, which treats "slices" of a
double[3] array as double[2] arrays, is strictly conforming in
both C99 and C11. If double[2] could have a stricter alignment
requirement than double, its behavior would be undefined under any
implementation that imposes such an alignment.
#include <stdio.h>
typedef double pair[2];
static void print(pair *p) {
printf("%g %g\n", (*p)[0], (*p)[1]);
}
int main(void) {
double arr[3] = { 10.0, 20.0, 30.0 };
pair *p0 = (pair*)&arr[0];
pair *p1 = (pair*)&arr[1];
print(p0);
print(p1);
}
If you mean the example program as part of an argument, it's
a circular argument. The program is strictly conforming if
and only if the alignment of double[2] must be the same as
the alignment of double. Saying the given program is strictly
conforming is just a sneaky way of begging the question.
I partly agree with your comment re alignment in C99/N1256, in the
sense that apparently there is an /expectation/ that alignment of
arrays must match the alignment of their elements. However, I
don't find any statement, or combination of statements, in
C99/N1256 that either requires or logically implies that such a
limitation must hold. This omission means some code that looks
reasonable might have undefined behavior. Consider for example
the following code fragment, accepted under C99 (and also C90):
int a23[2][3];
int a32[3][2];
int (*a)[];
int (*b)[2] = a32;
int (*c)[3] = a23;
a = a23;
b = a;
a = a32;
c = a;
Does this code have undefined behavior or not? In particular, are
the assignments to b and c okay, which wouldn't be allowed without
using 'a' as an intermediary? AFAICS the Standard doesn't require
the alignments of the types (int[2]) and (int[3]) to be the same.
(To simplify the discussion let's assume the alignment of (int[])
is the same as that of (int) - this doesn't change the question in
any significant way.) If indeed it is the case that the Standard
does not either require or logically imply that the alignments of
these two types must be the same, then an implementation is free
to make them different, which means the program has undefined
behavior. Furthermore such a possibility isn't that farfetched.
If we add a few lines
b[2][1] = 0;
c[1][2] = 0;
we still have acceptable standard C code (ie, does not require a
diagnostic), yet it certainly crosses into undefined behavior.
If we take the Standard at its word, then the alignments of the
types involved here are not constrained to have the same value,
and when they are different the semantics of pointer conversion
explicitly deems such conversions undefined behavior.
Let me say again that I think the Standard was written with the
expectation, and also is read by most people as meaning to imply,
that the alignment of array types will be the same as that of
their elements. However I don't find any text, either normative
or informative, in the Standard itself (ie, pre-C11) that supports
this supposition.