The following type attributes are supported on most targets.
aligned
¶aligned (alignment)
The aligned
attribute specifies a minimum alignment (in bytes) for
variables of the specified type. When specified, alignment must be
a power of 2. Specifying no alignment argument implies the maximum
alignment for the target, which is often, but by no means always, 8 or 16
bytes. For example, the declarations:
struct __attribute__ ((aligned (8))) S { short f[3]; }; typedef int more_aligned_int __attribute__ ((aligned (8)));
force the compiler to ensure (as far as it can) that each variable whose
type is struct S
or more_aligned_int
is allocated and
aligned at least on a 8-byte boundary. On a SPARC, having all
variables of type struct S
aligned to 8-byte boundaries allows
the compiler to use the ldd
and std
(doubleword load and
store) instructions when copying one variable of type struct S
to
another, thus improving run-time efficiency.
Note that the alignment of any given struct
or union
type
is required by the ISO C standard to be at least a perfect multiple of
the lowest common multiple of the alignments of all of the members of
the struct
or union
in question. This means that you can
effectively adjust the alignment of a struct
or union
type by attaching an aligned
attribute to any one of the members
of such a type, but the notation illustrated in the example above is a
more obvious, intuitive, and readable way to request the compiler to
adjust the alignment of an entire struct
or union
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
or union
type. Alternatively, you can leave out the alignment factor
and just ask the compiler to align a type to the maximum
useful alignment for the target machine you are compiling for. For
example, you could write:
struct __attribute__ ((aligned)) S { short f[3]; };
Whenever you leave out the alignment factor in an aligned
attribute specification, the compiler automatically sets the alignment
for the type to the largest alignment that is ever used for any data
type on the target machine you are compiling for. Doing this can often
make copy operations more efficient, because the compiler can use
whatever instructions copy the biggest chunks of memory when performing
copies to or from the variables that have types that you have aligned
this way.
In the example above, if the size of each short
is 2 bytes, then
the size of the entire struct S
type is 6 bytes. The smallest
power of two that is greater than or equal to that is 8, so the
compiler sets the alignment for the entire struct S
type to 8
bytes.
Note that although you can ask the compiler to select a time-efficient alignment for a given type and then declare only individual stand-alone objects of that type, the compiler’s ability to select a time-efficient alignment is primarily useful only when you plan to create arrays of variables having the relevant (efficiently aligned) type. If you declare or use arrays of variables of an efficiently-aligned type, then it is likely that your program also does pointer arithmetic (or subscripting, which amounts to the same thing) on pointers to the relevant type, and the code that the compiler generates for these pointer arithmetic operations is often more efficient for efficiently-aligned types than for other types.
Note that the effectiveness of aligned
attributes may be limited
by inherent limitations in your linker. On many systems, the linker is
only able to arrange for variables to be aligned up to a certain maximum
alignment. (For some linkers, the maximum supported alignment may
be very very small.) If your linker is only able to align variables
up to a maximum of 8-byte alignment, then specifying aligned (16)
in an __attribute__
still only provides you with 8-byte
alignment. See your linker documentation for further information.
When used on a struct, or struct member, the aligned
attribute can
only increase the alignment; in order to decrease it, the packed
attribute must be specified as well. When used as part of a typedef, the
aligned
attribute can both increase and decrease alignment, and
specifying the packed
attribute generates a warning.
alloc_size (position)
¶alloc_size (position-1, position-2)
The alloc_size
type attribute may be applied to the definition
of a type of a function that returns a pointer and takes at least one
argument of an integer type. It indicates that the returned pointer
points to an object whose size is given by the function argument at
position-1, or by the product of the arguments at position-1
and position-2. Meaningful sizes are positive values less than
PTRDIFF_MAX
. Other sizes are disagnosed when detected. GCC uses
this information to improve the results of __builtin_object_size
.
For instance, the following declarations
typedef __attribute__ ((alloc_size (1, 2))) void* calloc_type (size_t, size_t); typedef __attribute__ ((alloc_size (1))) void* malloc_type (size_t);
specify that calloc_type
is a type of a function that, like
the standard C function calloc
, returns an object whose size
is given by the product of arguments 1 and 2, and that
malloc_type
, like the standard C function malloc
,
returns an object whose size is given by argument 1 to the function.
copy
¶copy (expression)
The copy
attribute applies the set of attributes with which
the type of the expression has been declared to the declaration
of the type to which the attribute is applied. The attribute is
designed for libraries that define aliases that are expected to
specify the same set of attributes as the aliased symbols.
The copy
attribute can be used with types, variables, or
functions. However, the kind of symbol to which the attribute is
applied (either varible or function) must match the kind of symbol
to which the argument refers.
The copy
attribute copies only syntactic and semantic attributes
but not attributes that affect a symbol’s linkage or visibility such as
alias
, visibility
, or weak
. The deprecated
attribute is also not copied. See Common Function Attributes.
See Common Variable Attributes.
For example, suppose struct A
below is defined in some third
party library header to have the alignment requirement N
and
to force a warning whenever a variable of the type is not so aligned
due to attribute packed
. Specifying the copy
attribute
on the definition on the unrelated struct B
has the effect of
copying all relevant attributes from the type referenced by the pointer
expression to struct B
.
struct __attribute__ ((aligned (N), warn_if_not_aligned (N))) A { /* … */ }; struct __attribute__ ((copy ( (struct A *)0)) B { /* … */ };
deprecated
¶deprecated (msg)
The deprecated
attribute results in a warning if the type
is used anywhere in the source file. This is useful when identifying
types that are expected to be removed in a future version of a program.
If possible, the warning also includes the location of the declaration
of the deprecated type, to enable users to easily find further
information about why the type is deprecated, or what they should do
instead. Note that the warnings only occur for uses and then only
if the type is being applied to an identifier that itself is not being
declared 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. No warning is issued for line 4 because T2 is not explicitly deprecated. Line 5 has no warning because T3 is explicitly deprecated. Similarly for line 6. The optional msg argument, which must be a string, is printed in the warning if present. Control characters in the string will be replaced with escape sequences, and if the -fmessage-length option is set to 0 (its default value) then any newline characters will be ignored.
The deprecated
attribute can also be used for functions and
variables (see Declaring Attributes of Functions, see Specifying Attributes of Variables.)
The message attached to the attribute is affected by the setting of the -fmessage-length option.
designated_init
¶This attribute may only be applied to structure types. It indicates that any initialization of an object of this type must use designated initializers rather than positional initializers. The intent of this attribute is to allow the programmer to indicate that a structure’s layout may change, and that therefore relying on positional initialization will result in future breakage.
GCC emits warnings based on this attribute by default; use -Wno-designated-init to suppress them.
hardbool
¶hardbool (false_value)
hardbool (false_value, true_value)
This attribute may only be applied to integral types in C, to introduce
hardened boolean types. It turns the integral type into a boolean-like
type with the same size and precision, that uses the specified values as
representations for false
and true
. Underneath, it is
actually an enumerated type, but its observable behavior is like that of
_Bool
, except for the strict internal representations, verified
by runtime checks.
If true_value is omitted, the bitwise negation of false_value is used. If false_value is omitted, zero is used. The named representation values must be different when converted to the original integral type. Narrower bitfields are rejected if the representations become indistinguishable.
Values of such types automatically decay to _Bool
, at which
point, the selected representation values are mapped to the
corresponding _Bool
values. When the represented value is not
determined, at compile time, to be either false_value or
true_value, runtime verification calls __builtin_trap
if it
is neither. This is what makes them hardened boolean types.
When converting scalar types to such hardened boolean types, implicitly
or explicitly, behavior corresponds to a conversion to _Bool
,
followed by a mapping from false
and true
to
false_value and true_value, respectively.
typedef char __attribute__ ((__hardbool__ (0x5a))) hbool; hbool first = 0; /* False, stored as (char)0x5a. */ hbool second = !first; /* True, stored as ~(char)0x5a. */ static hbool zeroinit; /* False, stored as (char)0x5a. */ auto hbool uninit; /* Undefined, may trap. */
When zero-initializing a variable or field of hardened boolean type
(presumably held in static storage) the implied zero initializer gets
converted to _Bool
, and then to the hardened boolean type, so
that the initial value is the hardened representation for false
.
Using that value is well defined. This is not the case when
variables and fields of such types are uninitialized (presumably held in
automatic or dynamic storage): their values are indeterminate, and using
them invokes undefined behavior. Using them may trap or not, depending
on the bits held in the storage (re)used for the variable, if any, and
on optimizations the compiler may perform on the grounds that using
uninitialized values invokes undefined behavior.
Users of -ftrivial-auto-var-init should be aware that the bit
patterns used as initializers are not converted to
hardbool
types, so using a hardbool
variable that is
implicitly initialized by the -ftrivial-auto-var-init may trap
if the representations values chosen for false
and true
do
not match the initializer.
Since this is a language extension only available in C, interoperation with other languages may pose difficulties. It should interoperate with Ada Booleans defined with the same size and equivalent representation clauses, and with enumerations or other languages’ integral types that correspond to C’s chosen integral type.
may_alias
¶Accesses through pointers to types with this attribute are not subject to type-based alias analysis, but are instead assumed to be able to alias any other type of objects. In the context of section 6.5 paragraph 7 of the C99 standard, an lvalue expression dereferencing such a pointer is treated like having a character type. See -fstrict-aliasing for more information on aliasing issues. This extension exists to support some vector APIs, in which pointers to one vector type are permitted to alias pointers to a different vector type.
Note that an object of a type with this attribute does not have any special semantics.
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
with short
in the variable
declaration, the above program would abort when compiled with
-fstrict-aliasing, which is on by default at -O2 or
above.
mode (mode)
¶This attribute specifies the data type for the declaration—whichever type corresponds to the mode mode. This in effect lets you request an integer or floating-point type according to its width.
See Machine Modes in GNU Compiler Collection (GCC) Internals,
for a list of the possible keywords for mode.
You may also specify a mode of byte
or __byte__
to
indicate the mode corresponding to a one-byte integer, word
or
__word__
for the mode of a one-word integer, and pointer
or __pointer__
for the mode used to represent pointers.
objc_root_class (Objective-C and Objective-C++ only)
¶This attribute marks a class as being a root class, and thus allows the compiler to elide any warnings about a missing superclass and to make additional checks for mandatory methods as needed.
packed
¶This attribute, attached to a struct
, union
, or C++ class
type definition, specifies that each of its members (other than zero-width
bit-fields) is placed to minimize the memory required. This is equivalent
to specifying the packed
attribute on each of the members.
When attached to an enum
definition, the packed
attribute
indicates that the smallest integral type should be used.
Specifying the -fshort-enums flag on the command line
is equivalent to specifying the packed
attribute on all enum
definitions.
In the following example struct my_packed_struct
’s members are
packed closely together, but the internal layout of its s
member
is not packed—to do that, struct my_unpacked_struct
needs to
be packed too.
struct my_unpacked_struct { char c; int i; }; struct __attribute__ ((__packed__)) my_packed_struct { char c; int i; struct my_unpacked_struct s; };
You may only specify the packed
attribute on the definition
of an enum
, struct
, union
, or class
,
not on a typedef
that does not also define the enumerated type,
structure, union, or class.
scalar_storage_order ("endianness")
¶When attached to a union
or a struct
, this attribute sets
the storage order, aka endianness, of the scalar fields of the type, as
well as the array fields whose component is scalar. The supported
endiannesses are big-endian
and little-endian
. The attribute
has no effects on fields which are themselves a union
, a struct
or an array whose component is a union
or a struct
, and it is
possible for these fields to have a different scalar storage order than the
enclosing type.
Note that neither pointer nor vector fields are considered scalar fields in this context, so the attribute has no effects on these fields.
This attribute is supported only for targets that use a uniform default scalar storage order (fortunately, most of them), i.e. targets that store the scalars either all in big-endian or all in little-endian.
Additional restrictions are enforced for types with the reverse scalar storage order with regard to the scalar storage order of the target:
union
or a
struct
with reverse scalar storage order is not permitted and yields
an error.
union
or a struct
with reverse scalar storage order is
permitted but yields a warning, unless -Wno-scalar-storage-order
is specified.
union
or a struct
with reverse
scalar storage order is permitted.
These restrictions exist because the storage order attribute is lost when the address of a scalar or the address of an array with scalar component is taken, so storing indirectly through this address generally does not work. The second case is nevertheless allowed to be able to perform a block copy from or to the array.
Moreover, the use of type punning or aliasing to toggle the storage order is not supported; that is to say, if a given scalar object can be accessed through distinct types that assign a different storage order to it, then the behavior is undefined.
strub
¶This attribute defines stack-scrubbing properties of functions and
variables, so that functions that access sensitive data can have their
stack frames zeroed-out upon returning or propagating exceptions. This
may be enabled explicitly, by selecting certain strub
modes for
specific functions, or implicitly, by means of strub
variables.
Being a type attribute, it attaches to types, even when specified in function and variable declarations. When applied to function types, it takes an optional string argument. When applied to a pointer-to-function type, if the optional argument is given, it gets propagated to the function type.
/* A strub variable. */ int __attribute__ ((strub)) var; /* A strub variable that happens to be a pointer. */ __attribute__ ((strub)) int *strub_ptr_to_int; /* A pointer type that may point to a strub variable. */ typedef int __attribute__ ((strub)) *ptr_to_strub_int_type; /* A declaration of a strub function. */ extern int __attribute__ ((strub)) foo (void); /* A pointer to that strub function. */ int __attribute__ ((strub ("at-calls"))) (*ptr_to_strub_fn)(void) = foo;
A function associated with at-calls
strub
mode
(strub("at-calls")
, or just strub
) undergoes interface
changes. Its callers are adjusted to match the changes, and to scrub
(overwrite with zeros) the stack space used by the called function after
it returns. The interface change makes the function type incompatible
with an unadorned but otherwise equivalent type, so every
declaration and every type that may be used to call the function must be
associated with this strub mode.
A function associated with internal
strub
mode
(strub("internal")
) retains an unmodified, type-compatible
interface, but it may be turned into a wrapper that calls the wrapped
body using a custom interface. The wrapper then scrubs the stack space
used by the wrapped body. Though the wrapped body has its stack space
scrubbed, the wrapper does not, so arguments and return values may
remain unscrubbed even when such a function is called by another
function that enables strub
. This is why, when compiling with
-fstrub=strict, a strub
context is not allowed to call
internal
strub
functions.
/* A declaration of an internal-strub function. */ extern int __attribute__ ((strub ("internal"))) bar (void); int __attribute__ ((strub)) baz (void) { /* Ok, foo was declared above as an at-calls strub function. */ foo (); /* Not allowed in strict mode, otherwise allowed. */ bar (); }
An automatically-allocated variable associated with the strub
attribute causes the (immediately) enclosing function to have
strub
enabled.
A statically-allocated variable associated with the strub
attribute causes functions that read it, through its strub
data type, to have strub
enabled. Reading data by dereferencing
a pointer to a strub
data type has the same effect. Note: The
attribute does not carry over from a composite type to the types of its
components, so the intended effect may not be obtained with non-scalar
types.
When selecting a strub
-enabled mode for a function that is not
explicitly associated with one, because of strub
variables or
data pointers, the function must satisfy internal
mode viability
requirements (see below), even when at-calls
mode is also viable
and, being more efficient, ends up selected as an optimization.
/* zapme is implicitly strub-enabled because of strub variables. Optimization may change its strub mode, but not the requirements. */ static int zapme (int i) { /* A local strub variable enables strub. */ int __attribute__ ((strub)) lvar; /* Reading strub data through a pointer-to-strub enables strub. */ lvar = * (ptr_to_strub_int_type) &i; /* Writing to a global strub variable does not enable strub. */ var = lvar; /* Reading from a global strub variable enables strub. */ return var; }
A strub
context is the body (as opposed to the interface) of a
function that has strub
enabled, be it explicitly, by
at-calls
or internal
mode, or implicitly, due to
strub
variables or command-line options.
A function of a type associated with the disabled
strub
mode (strub("disabled")
will not have its own stack space
scrubbed. Such functions cannot be called from within
strub
contexts.
In order to enable a function to be called from within strub
contexts without having its stack space scrubbed, associate it with the
callable
strub
mode (strub("callable")
).
When a function is not assigned a strub
mode, explicitly or
implicitly, the mode defaults to callable
, except when compiling
with -fstrub=strict, that causes strub
mode to default
to disabled
.
extern int __attribute__ ((strub ("callable"))) bac (void); extern int __attribute__ ((strub ("disabled"))) bad (void); /* Implicitly disabled with -fstrub=strict, otherwise callable. */ extern int bah (void); int __attribute__ ((strub)) bal (void) { /* Not allowed, bad is not strub-callable. */ bad (); /* Ok, bac is strub-callable. */ bac (); /* Not allowed with -fstrub=strict, otherwise allowed. */ bah (); }
Function types marked callable
and disabled
are not
mutually compatible types, but the underlying interfaces are compatible,
so it is safe to convert pointers between them, and to use such pointers
or alternate declarations to call them. Interfaces are also
interchangeable between them and internal
(but not
at-calls
!), but adding internal
to a pointer type will not
cause the pointed-to function to perform stack scrubbing.
void __attribute__ ((strub)) bap (void) { /* Assign a callable function to pointer-to-disabled. Flagged as not quite compatible with -Wpedantic. */ int __attribute__ ((strub ("disabled"))) (*d_p) (void) = bac; /* Not allowed: calls disabled type in a strub context. */ d_p (); /* Assign a disabled function to pointer-to-callable. Flagged as not quite compatible with -Wpedantic. */ int __attribute__ ((strub ("callable"))) (*c_p) (void) = bad; /* Ok, safe. */ c_p (); /* Assign an internal function to pointer-to-callable. Flagged as not quite compatible with -Wpedantic. */ c_p = bar; /* Ok, safe. */ c_p (); /* Assign an at-calls function to pointer-to-callable. Flaggged as incompatible. */ c_p = bal; /* The call through an interface-incompatible type will not use the modified interface expected by the at-calls function, so it is likely to misbehave at runtime. */ c_p (); }
Strub
contexts are never inlined into non-strub
contexts.
When an internal
-strub function is split up, the wrapper can
often be inlined, but the wrapped body never is. A function
marked as always_inline
, even if explicitly assigned
internal
strub mode, will not undergo wrapping, so its body gets
inlined as required.
inline int __attribute__ ((strub ("at-calls"))) inl_atc (void) { /* This body may get inlined into strub contexts. */ } inline int __attribute__ ((strub ("internal"))) inl_int (void) { /* This body NEVER gets inlined, though its wrapper may. */ } inline int __attribute__ ((strub ("internal"), always_inline)) inl_int_ali (void) { /* No internal wrapper, so this body ALWAYS gets inlined, but it cannot be called from non-strub contexts. */ } void __attribute__ ((strub ("disabled"))) bat (void) { /* Not allowed, cannot inline into a non-strub context. */ inl_int_ali (); }
Some -fstrub=* command line options enable strub
modes
implicitly where viable. A strub
mode is only viable for a
function if the function is eligible for that mode, and if other
conditions, detailed below, are satisfied. If it’s not eligible for a
mode, attempts to explicitly associate it with that mode are rejected
with an error message. If it is eligible, that mode may be assigned
explicitly through this attribute, but implicit assignment through
command-line options may involve additional viability requirements.
A function is ineligible for at-calls
strub
mode if a
different strub
mode is explicitly requested, if attribute
noipa
is present, or if it calls __builtin_apply_args
.
At-calls
strub
mode, if not requested through the function
type, is only viable for an eligible function if the function is not
visible to other translation units, if it doesn’t have its address
taken, and if it is never called with a function type overrider.
/* bar is eligible for at-calls strub mode, but not viable for that mode because it is visible to other units. It is eligible and viable for internal strub mode. */ void bav () {} /* setp is eligible for at-calls strub mode, but not viable for that mode because its address is taken. It is eligible and viable for internal strub mode. */ void setp (void) { static void (*p)(void); = setp; }
A function is ineligible for internal
strub
mode if a
different strub
mode is explicitly requested, or if attribute
noipa
is present. For an always_inline
function, meeting
these requirements is enough to make it eligible. Any function that has
attribute noclone
, that uses such extensions as non-local labels,
computed gotos, alternate variable argument passing interfaces,
__builtin_next_arg
, or __builtin_return_address
, or that
takes too many (about 64Ki) arguments is ineligible, unless it is
always_inline
. For internal
strub
mode, all
eligible functions are viable.
/* flop is not eligible, thus not viable, for at-calls strub mode. Likewise for internal strub mode. */ __attribute__ ((noipa)) void flop (void) {} /* flip is eligible and viable for at-calls strub mode. It would be ineligible for internal strub mode, because of noclone, if it weren't for always_inline. With always_inline, noclone is not an obstacle, so it is also eligible and viable for internal strub mode. */ inline __attribute__ ((noclone, always_inline)) void flip (void) {}
transparent_union
¶This attribute, attached to a union
type definition, indicates
that any function parameter having that union type causes calls to that
function to be treated in a special way.
First, the argument corresponding to a transparent union type can be of
any type in the union; no cast is required. Also, if the union contains
a pointer type, the corresponding argument can be a null pointer
constant or a void pointer expression; and if the union contains a void
pointer type, the corresponding argument can be any pointer expression.
If the union member type is a pointer, qualifiers like const
on
the referenced type must be respected, just as with normal pointer
conversions.
Second, the argument is passed to the function using the calling conventions of the first member of the transparent union, not the calling conventions of the union itself. All members of the union must have the same machine representation; this is necessary for this argument passing to work properly.
Transparent unions are designed for library functions that have multiple
interfaces for compatibility reasons. For example, suppose the
wait
function must accept either a value of type int *
to
comply with POSIX, or a value of type union wait *
to comply with
the 4.1BSD interface. If wait
’s parameter were void *
,
wait
would accept both kinds of arguments, but it would also
accept any other pointer type and this would make argument type checking
less useful. Instead, <sys/wait.h>
might define the interface
as follows:
typedef union __attribute__ ((__transparent_union__)) { int *__ip; union wait *__up; } wait_status_ptr_t; pid_t wait (wait_status_ptr_t);
This interface allows either int *
or union wait *
arguments to be passed, using the int *
calling convention.
The program can call wait
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); }
unavailable
¶unavailable (msg)
The unavailable
attribute behaves in the same manner as the
deprecated
one, but emits an error rather than a warning. It is
used to indicate that a (perhaps previously deprecated
) type is
no longer usable.
The unavailable
attribute can also be used for functions and
variables (see Declaring Attributes of Functions, see Specifying Attributes of Variables.)
unused
¶When attached to a type (including a union
or a struct
),
this attribute means that variables of that type are meant to appear
possibly unused. GCC does not produce a warning for any variables of
that type, even if the variable appears to do nothing. This is often
the case with lock or thread classes, which are usually defined and then
not referenced, but contain constructors and destructors that have
nontrivial bookkeeping functions.
vector_size (bytes)
¶This attribute specifies the vector size for the type, measured in bytes. The type to which it applies is known as the base type. The bytes argument must be a positive power-of-two multiple of the base type size. For example, the following declarations:
typedef __attribute__ ((vector_size (32))) int int_vec32_t ; typedef __attribute__ ((vector_size (32))) int* int_vec32_ptr_t; typedef __attribute__ ((vector_size (32))) int int_vec32_arr3_t[3];
define int_vec32_t
to be a 32-byte vector type composed of int
sized units. With int
having a size of 4 bytes, the type defines
a vector of eight units, four bytes each. The mode of variables of type
int_vec32_t
is V8SI
. int_vec32_ptr_t
is then defined
to be a pointer to such a vector type, and int_vec32_arr3_t
to be
an array of three such vectors. See Using Vector Instructions through Built-in Functions, for details of
manipulating objects of vector types.
This attribute is only applicable to integral and floating scalar types. In function declarations the attribute applies to the function return type.
For example, the following:
__attribute__ ((vector_size (16))) float get_flt_vec16 (void);
declares get_flt_vec16
to be a function returning a 16-byte vector
with the base type float
.
visibility
¶In C++, attribute visibility (see Declaring Attributes of Functions) can also be applied to class, struct, union and enum types. Unlike other type attributes, the attribute must appear between the initial keyword and the name of the type; it cannot appear after the body of the type.
Note that the type visibility is applied to vague linkage entities associated with the class (vtable, typeinfo node, etc.). In particular, if a class is thrown as an exception in one shared object and caught in another, the class must have default visibility. Otherwise the two shared objects are unable to use the same typeinfo node and exception handling will break.
warn_if_not_aligned (alignment)
¶This attribute specifies a threshold for the structure field, measured in bytes. If the structure field is aligned below the threshold, a warning will be issued. For example, the declaration:
typedef unsigned long long __u64 __attribute__((aligned (4), warn_if_not_aligned (8))); struct foo { int i1; int i2; __u64 x; };
causes the compiler to issue an warning on struct foo
, like
‘warning: alignment 4 of 'struct foo' is less than 8’.
It is used to define struct foo
in such a way that
struct foo
has the same layout and the structure field x
has the same alignment when __u64
is aligned at either 4 or
8 bytes. Align struct foo
to 8 bytes:
struct __attribute__ ((aligned (8))) foo { int i1; int i2; __u64 x; };
silences the warning. The compiler also issues a warning, like ‘warning: 'x' offset 12 in 'struct foo' isn't aligned to 8’, when the structure field has the misaligned offset:
struct __attribute__ ((aligned (8))) foo { int i1; int i2; int i3; __u64 x; };
This warning can be disabled by -Wno-if-not-aligned.
To specify multiple attributes, separate them by commas within the double parentheses: for example, ‘__attribute__ ((aligned (16), packed))’.