>>>> "Colin" == Colin Rafferty
<colin(a)xemacs.org> writes:
Colin> Martin Buchholz writes:
>>>>>> "Colin" == Colin Rafferty
<colin.rafferty(a)msdw.com> writes:
Colin> Björn Torkelsson writes:
>>> The latest version of XEmacs updated from CVS yesterday
(2000-04-03) is
>>> uncompilable under SGI IRIX with the naitive SGI cc compiler.
Colin> I submitted the patch to xemacs-patches to undo Martin's changes
Colin> already. Here it is for your personal enjoyment.
Colin> * alloc.c (size_vector):
Colin> (make_vector_internal):
Colin> (make_bit_vector_internal):
Colin> (sweep_bit_vectors_1):
Colin> Replace calls to offsetof with STRETCHY_STRUCT_SIZEOF macro.
> I don't like reversing this change. Is the code in XEmacs
> ANSI-compliant? I think so.
Colin> I don't. While I don't have a copy of the standard, SGI compilers are
Colin> very good at following the standards.
Your intuition is correct. As usual, I was wrong. Arguments of this
type are best won by citing chapter and verse.
offsetof(type, member-designator)
which expands to an integer constant expression that has
type size_t, the value of which is the offset in bytes, to
the structure member (designated by member-designator), from
the beginning of its structure (designated by type). The
member-designator shall be such that given
static type t;
then the expression &(t.member-designator) evaluates to an
address constant. (If the specified member is a bit-field,
the behavior is undefined.)
We can put back the original code, but I would like to revisit the
naming scheme. "stretchy struct" is a phrase adopted from some
proprietary debugging tool (Insure, if I recall). This practice has
not been legal ANSI C, but all known compilers support it. C9x has
created a legal way to create such structs, and called the last member
"flexible array member". Sometime when c9x compilers are ubiquitous
(perhaps even in my lifetime), we can change the struct declaration
syntax to omit the bogus [1] (ceci n'est pas une footnote).
So let's audit all the occurrences of offsetof in the sources, and
change the ones required back to use STRETCHY_STRUCT_SIZEOF, except
let's use a naming convention like this:
#define FLEXIBLE_ARRAY_STRUCT_SIZEOF(flexible_array_structtype, flexible_array_member,
flexible_array_length) \
More chapter and verse follows:
[#15] As a special case, the last element of a structure may
be an incomplete array type. This is called a flexible
array member, and the size of the structure shall be equal
to the offset of the last element of an otherwise identical
structure that replaces the flexible array member with an
array of one element. When an lvalue whose type is a
structure with a flexible array member is used to access an
object, it behaves as if that member were replaced by the
longest array that would not make the structure larger than
the object being accessed. If this array would have no
elements, then it behaves as if it has one element, but the
behavior is undefined if any attempt is made to access that
element.
[#16] After the declarations:
struct s { int n; double d[]; };
struct ss { int n; double d[1]; };
the three expressions:
sizeof (struct s)
offsetof(struct s, d)
offsetof(struct ss, d)
have the same value. The structure struct s has a flexible
array member d.
[#17] If sizeof (double) is 8, then after the following code
is executed:
struct s *s1;
struct s *s2;
s1 = malloc(sizeof (struct s) + 64);
s2 = malloc(sizeof (struct s) + 46);
and assuming that the calls to malloc succeed, s1 and s2
behave as if they had been declared as:
struct { int n; double d[8]; } *s1;
struct { int n; double d[5]; } *s2;
[#18] Following the further successful assignments:
s1 = malloc(sizeof (struct s) + 10);
s2 = malloc(sizeof (struct s) + 6);
they then behave as if they had been declared as:
struct { int n; double d[1]; } *s1, *s2;
and:
double *dp;
dp = &(s1->d[0]); // Permitted
*dp = 42; // Permitted
dp = &(s2->d[0]); // Permitted
*dp = 42; // Undefined behavior