Next: Alignment,Previous: Variable Attributes,Up: C Extensions
5.32 Specifying Attributes of Types
The keyword __attribute__
allows you to specify specialattributes of struct
and union
types when you define suchtypes. This keyword is followed by an attribute specification insidedouble parentheses. Six attributes are currently defined for types:aligned
, packed
, transparent_union
, unused
,deprecated
and may_alias
. Other attributes are defined forfunctions (see Function Attributes) and for variables(see Variable Attributes).
You may also specify any one of these attributes with `__'preceding and following its keyword. This allows you to use theseattributes in header files without being concerned about a possiblemacro of the same name. For example, you may use __aligned__
instead of aligned
.
You may specify the aligned
and transparent_union
attributes either in a typedef
declaration or just past theclosing curly brace of a complete enum, struct or union typedefinition and the packed
attribute only past the closingbrace of a definition.
You may also specify attributes between the enum, struct or uniontag and the name of the type rather than after the closing brace.
See Attribute Syntax, for details of the exact syntax for usingattributes.
-
This attribute specifies a minimum alignment (in bytes) for variablesof the specified type. For example, the declarations:
struct S { short f[3]; } __attribute__ ((aligned (8))); typedef int more_aligned_int __attribute__ ((aligned (8)));
force the compiler to insure (as far as it can) that each variable whosetype is
struct S
ormore_aligned_int
will be allocated andaligned at least on a 8-byte boundary. On a SPARC, having allvariables of typestruct S
aligned to 8-byte boundaries allowsthe compiler to use theldd
andstd
(doubleword load andstore) instructions when copying one variable of typestruct S
toanother, thus improving run-time efficiency.Note that the alignment of any given
struct
orunion
typeis required by the ISO C standard to be at least a perfect multiple ofthe lowest common multiple of the alignments of all of the members ofthestruct
orunion
in question. This means that you caneffectively adjust the alignment of astruct
orunion
type by attaching analigned
attribute to any one of the membersof such a type, but the notation illustrated in the example above is amore obvious, intuitive, and readable way to request the compiler toadjust the alignment of an entirestruct
orunion
type.As in the preceding example, you can explicitly specify the alignment(in bytes) that you wish the compiler to use for a given
struct
orunion
type. Alternatively, you can leave out the alignment factorand just ask the compiler to align a type to the maximumuseful alignment for the target machine you are compiling for. Forexample, you could write:struct S { short f[3]; } __attribute__ ((aligned));
Whenever you leave out the alignment factor in an
aligned
attribute specification, the compiler automatically sets the alignmentfor the type to the largest alignment which is ever used for any datatype on the target machine you are compiling for. Doing this can oftenmake copy operations more efficient, because the compiler can usewhatever instructions copy the biggest chunks of memory when performingcopies to or from the variables which have types that you have alignedthis way.In the example above, if the size of each
short
is 2 bytes, thenthe size of the entirestruct S
type is 6 bytes. The smallestpower of two which is greater than or equal to that is 8, so thecompiler sets the alignment for the entirestruct S
type to 8bytes.Note that although you can ask the compiler to select a time-efficientalignment for a given type and then declare only individual stand-aloneobjects of that type, the compiler's ability to select a time-efficientalignment is primarily useful only when you plan to create arrays ofvariables having the relevant (efficiently aligned) type. If youdeclare or use arrays of variables of an efficiently-aligned type, thenit is likely that your program will also be doing pointer arithmetic (orsubscripting, which amounts to the same thing) on pointers to therelevant type, and the code that the compiler generates for thesepointer arithmetic operations will often be more efficient forefficiently-aligned types than for other types.
The
aligned
attribute can only increase the alignment; but youcan decrease it by specifyingpacked
as well. See below.Note that the effectiveness of
aligned
attributes may be limitedby inherent limitations in your linker. On many systems, the linker isonly able to arrange for variables to be aligned up to a certain maximumalignment. (For some linkers, the maximum supported alignment maybe very very small.) If your linker is only able to align variablesup to a maximum of 8 byte alignment, then specifyingaligned(16)
in an__attribute__
will still only provide you with 8 bytealignment. See your linker documentation for further information.
-
This attribute, attached to
struct
orunion
typedefinition, specifies that each member of the structure or union isplaced to minimize the memory required. When attached to anenum
definition, it indicates that the smallest integral type should be used.Specifying this attribute for
struct
andunion
types isequivalent to specifying thepacked
attribute on each of thestructure or union members. Specifying the -fshort-enumsflag on the line is equivalent to specifying thepacked
attribute on allenum
definitions.In the following example
struct my_packed_struct
's members arepacked closely together, but the internal layout of itss
memberis not packed—to do that,struct my_unpacked_struct
would need tobe packed too.struct my_unpacked_struct { char c; int i; }; struct my_packed_struct __attribute__ ((__packed__)) { char c; int i; struct my_unpacked_struct s; };
You may only specify this attribute on the definition of a
enum
,struct
orunion
, not on atypedef
which does notalso define the enumerated type, structure or union.
-
This attribute, attached to a
union
type definition, indicatesthat any function parameter having that union type causes calls to thatfunction to be treated in a special way.First, the argument corresponding to a transparent union type can be ofany type in the union; no cast is required. Also, if the union containsa pointer type, the corresponding argument can be a null pointerconstant or a void pointer expression; and if the union contains a voidpointer type, the corresponding argument can be any pointer expression. If the union member type is a pointer, qualifiers like
const
onthe referenced type must be respected, just as with normal pointerconversions.Second, the argument is passed to the function using the callingconventions of the first member of the transparent union, not the callingconventions of the union itself. All members of the union must have thesame machine representation; this is necessary for this argument passingto work properly.
Transparent unions are designed for library functions that have multipleinterfaces for compatibility reasons. For example, suppose the
wait
function must accept either a value of typeint *
tocomply with Posix, or a value of typeunion wait *
to comply withthe 4.1BSD interface. Ifwait
's parameter werevoid *
,wait
would accept both kinds of arguments, but it would alsoaccept any other pointer type and this would make argument type checkingless useful. Instead,<sys/wait.h>
might define the interfaceas follows:typedef union { int *__ip; union wait *__up; } wait_status_ptr_t __attribute__ ((__transparent_union__)); pid_t wait (wait_status_ptr_t);
This interface allows either
int *
orunion wait *
arguments to be passed, using theint *
calling convention. The program can callwait
with arguments of either type:int w1 () { int w; return wait (&w); } int w2 () { union wait w; return wait (&w); }
With this interface,
wait
's implementation might look like this:pid_t wait (wait_status_ptr_t p) { return waitpid (-1, p.__ip, 0); }
-
When attached to a type (including a
union
or astruct
),this attribute means that variables of that type are meant to appearpossibly unused. GCC will not produce a warning for any variables ofthat type, even if the variable appears to do nothing. This is oftenthe case with lock or thread classes, which are usually defined and thennot referenced, but contain constructors and destructors that havenontrivial bookkeeping functions.
-
The
deprecated
attribute results in a warning if the typeis used anywhere in the source file. This is useful when identifyingtypes that are expected to be removed in a future version of a program. If possible, the warning also includes the location of the declarationof the deprecated type, to enable users to easily find furtherinformation about why the type is deprecated, or what they should doinstead. Note that the warnings only occur for uses and then onlyif the type is being applied to an identifier that itself is not beingdeclared as deprecated.typedef int T1 __attribute__ ((deprecated)); T1 x; typedef T1 T2; T2 y; typedef T1 T3 __attribute__ ((deprecated)); T3 z __attribute__ ((deprecated));
results in a warning on line 2 and 3 but not lines 4, 5, or 6. Nowarning is issued for line 4 because T2 is not explicitlydeprecated. Line 5 has no warning because T3 is explicitlydeprecated. Similarly for line 6.
The
deprecated
attribute can also be used for functions andvariables (see Function Attributes, see Variable Attributes.)
-
Accesses to objects with types with this attribute are not subjected totype-based alias analysis, but are instead assumed to be able to aliasany other type of objects, just like the
char
type. See -fstrict-aliasing for more information on aliasing issues.Example of use:
typedef short __attribute__((__may_alias__)) short_a; int main (void) { int a = 0x12345678; short_a *b = (short_a *) &a; b[1] = 0; if (a == 0x12345678) abort(); exit(0); }
If you replaced
short_a
withshort
in the variabledeclaration, the above program would abort when compiled with-fstrict-aliasing, which is on by default at -O2 orabove in recent GCC versions.5.32.1 ARM Type Attributes
On those ARM targets that support
dllimport
(such as SymbianOS), you can use thenotshared
attribute to indicate that thevirtual table and other similar data for a class should not beexported from a DLL. For example:class __declspec(notshared) C { public: __declspec(dllimport) C(); virtual void f(); } __declspec(dllexport) C::C() {}
In this code,
C::C
is exported from the current DLL, but thevirtual table forC
is not exported. (You can use__attribute__
instead of__declspec
if you prefer, butmost Symbian OS code uses__declspec
.)5.32.2 i386 Type Attributes
Two attributes are currently defined for i386 configurations:
ms_struct
andgcc_struct
-
If
packed
is used on a structure, or if bit-fields are usedit may be that the Microsoft ABI packs them differentlythan GCC would normally pack them. Particularly when moving packeddata between functions compiled with GCC and the native Microsoft compiler(either via function call or as data in a file), it may be necessary to accesseither format.Currently -m[no-]ms-bitfields is provided for the Microsoft Windows X86compilers to match the native Microsoft compiler.
aligned (
alignment
)
packed
transparent_union
unused
deprecated
may_alias
ms_struct
gcc_struct
To specify multiple attributes, separate them by commas within thedouble parentheses: for example, `__attribute__ ((aligned (16),packed))'.