Structure and union specifiers

Previous Table of Contents "New C Standard" commentary


                struct-or-union identifieropt { struct-declaration-list }
                struct-or-union identifier

struct-or-union: struct union

struct-declaration-list: struct-declaration struct-declaration-list struct-declaration

struct-declaration: specifier-qualifier-list struct-declarator-list ;

specifier-qualifier-list: type-specifier specifier-qualifier-listopt type-qualifier specifier-qualifier-listopt

struct-declarator-list: struct-declarator struct-declarator-list , struct-declarator

struct-declarator: declarator declaratoropt : constant-expression

1391 A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), except that the last member of a structure with more than one named member may have incomplete array type;

1392 such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array.

1393 The expression that specifies the width of a bit-field shall be an integer constant expression that has a nonnegative value that shall not exceed the numberwidth of bits in an object of the type that iswould be specified ifwere the colon and expression are omitted.

1394 If the value is zero, the declaration shall have no declarator.

1395 A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type.

1396 As discussed in 6.2.5, a structure is a type consisting of a sequence of members, whose storage is allocated in an ordered sequence, and a union is a type consisting of a sequence of members whose storage overlap.

1397 Structure and union specifiers have the same form.

1398 The keywords struct and union indicate that the type being specified is, respectively, a structure type or a union type.

1399 The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type, within a translation unit.

1400 The struct-declaration-list is a sequence of declarations for the members of the structure or union.

1401 If the struct-declaration-list contains no named members, the behavior is undefined.

1402 The type is incomplete until after the } that terminates the list.

1403 A member of a structure or union may have any object type other than a variably modified type.103)

1404 In addition, a member may be declared to consist of a specified number of bits (including a sign bit, if any).

1405 Such a member is called a bit-field;104)

1406 its width is preceded by a colon.

1407 A bit-field is interpreted as a signed or unsigned integer type consisting of the specified number of bits.105)

1408 If the value 0 or 1 is stored into a nonzero-width bit-field of type _Bool, the value of the bit-field shall compare equal to the value stored.

1409 An implementation may allocate any addressable storage unit large enough to hold a bit-field.

1410 If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit.

1411 If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined.

1412 The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined.

1413 The alignment of the addressable storage unit is unspecified.

1414 A bit-field declaration with no declarator, but only a colon and a width, indicates an unnamed bit-field.106)

1415 As a special case, a bit-field structure member with a width of 0 indicates that no further bit-field is to be packed into the unit in which the previous bit-field, if any, was placed.

1416 103) A structure or union can not contain a member with a variably modified type because member names are not ordinary identifiers as defined in 6.2.3.

1417 104) The unary & (address-of) operator cannot be applied to a bit-field object;

1418 thus, there are no pointers to or arrays of bit-field objects.

1419 105) As specified in 6.7.2 above, if the actual type specifier used is int or a typedef-name defined as int, then it is implementation-defined whether the bit-field is signed or unsigned.

1420 106) An unnamed bit-field structure member is useful for padding to conform to externally imposed layouts.

1421 Each non-bit-field member of a structure or union object is aligned in an implementation-defined manner appropriate to its type.

1422 Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared.

1423 A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa.

1424 There may be unnamed padding within a structure object, but not at its beginning.

1425 The size of a union is sufficient to contain the largest of its members.

1426 The value of at most one of the members can be stored in a union object at any time.

1427 A pointer to a union object, suitably converted, points to each of its members (or if a member is a bit-field, then to the unit in which it resides), and vice versa.

1428 There may be unnamed padding at the end of a structure or union.

1429 As a special case, the last element of a structure with more than one named member may have an incomplete array type;

1430 this is called a flexible array member.

1431 With two exceptions In most situations, the flexible array member is ignored.

1432 First, 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 unspecified length.106) In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply.

1433 SecondHowever, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed;

1434 the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array.

1435 If this array would have no elements, it behaves as if it had one element but the behavior is undefined if any attempt is made to access that element or to generate a pointer one past it.

1436 EXAMPLE Assuming that all array members are aligned the same, 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.

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, the objects pointed to by s1 and s2 behave, for most purposes, as if the identifiers had been declared as:

        struct { int n; double d[8]; } *s1;
        struct { int n; double d[5]; } *s2;

Following the further successful assignments:

        s1 = malloc(sizeof (struct s) + 10);
        s2 = malloc(sizeof (struct s) +  6);

they then behave as if the declarations were:

        struct { int n; double d[1]; } *s1, *s2;


        double *dp;
        dp = &(s1->d[0]);        // valid
        *dp = 42;                // valid
        dp = &(s2->d[0]);        // valid
        *dp = 42;                // undefined behavior

The assignment:

        *s1 = *s2;

only copies the member n ; if any of the array elements are within the first sizeof (struct s) bytes of the structure, these might be copied or simply overwritten with indeterminate values. and not any of the array elements. Similarly:

        struct s  t1 = { 0 };            // valid
        struct s  t2 = { 2 };            // valid
        struct ss tt = { 1, { 4.2 }};    // valid
        struct s  t3 = { 1, { 4.2 }};    // invalid: there is nothing for the 4.2 to initialize

t1.n = 4; // valid t1.d[0] = 4.2; // undefined behavior

1437 106) The length is unspecified to allow for the fact that implementations may give array members different alignments according to their lengths.

1438 Forward references: tags (


Created at: 2008-01-30 02:39:43 The text from WG14/N1256 is copyright © ISO