8.11 Variable Attributes

The compiler keyword __attribute__ allows you to specify special attributes of variables or structure fields. This keyword is followed by an attribute specification inside double parentheses.

You may also specify attributes with __ (double underscore) preceding and following each keyword (e.g., __aligned __ instead of aligned). This allows you to use them in header files without being concerned about a possible macro of the same name.

To specify multiple attributes, separate them by commas within the double parentheses, for example:

__attribute__ ((aligned (16), packed)).

Note: It is important to use variable attributes consistently throughout a project. For example, if a variable is defined in file A with the an attribute, and declared extern in file B without the same attribute, then a link error might result.

address (addr)

Specify an absolute virtual address for the variable. This attribute can be used in conjunction with a section attribute.

This attribute can be used to start a group of variables at a specific address:

 int foo __attribute__((section("mysection"),address(0xA0001000)));

 int bar __attribute__((section("mysection")));

 int baz __attribute__((section("mysection")));

Keep in mind that the compiler performs no error checking on the specified address. The section will be located at the specified address regardless of the memory-region ranges listed in the linker script or the actual ranges on the target device. This application code is responsible for ensuring that the address is valid for the target device and application.

In addition, to make effective use of absolute sections and the new best-fit allocator, standard program-memory and data-memory sections should not be mapped in the linker script. The built-in linker script does not map most standard sections such as the .text, .data, .bss, or .ramfunc section. By not mapping these sections in the linker script, we allow these sections to be allocated using the best-fit allocator rather than the sequential allocator. Sections that are unmapped in the linker script can flow around absolute sections whereas sections that are linker-script mapped are grouped together and allocated sequentially, potentially causing conflicts with absolute sections.

Note: In almost all cases, you will want to combine the address attribute with the space attribute to indicate code or data with space(prog) or space(data), respectively. Also, see the description for the space attribute.

aligned (n)

The attributed variable will be aligned on the next n byte boundary.

The aligned attribute can also be used on a structure member. Such a member will be aligned to the indicated boundary within the structure.

If the alignment value n is omitted, the alignment of the variable is set 8 (the largest alignment value for a basic data type).

Note that the aligned attribute is used to increase the alignment of a variable, not reduce it. To decrease the alignment value of a variable, use the packed attribute.

cleanup (function)

Indicate a function to call when the attributed automatic function scope variable goes out of scope.

The indicated function should take a single parameter, a pointer to a type compatible with the attributed variable, and have void return type.

externally_visible

This attribute when used with a global object ensures the object remains visible outside the current compilation unit. This might prevent certain optimizations from being performed on the object.

packed

The attributed variable or structure member will have the smallest possible alignment. That is, no alignment padding storage will be allocated for the declaration. Used in combination with the aligned attribute, packed can be used to set an arbitrary alignment restriction greater or lesser than the default alignment for the type of the variable or structure member.

persistent

This attribute prevents the startup code's data-initialization code from initializing the variable. This behavior can be useful when you want to preserve the value across a soft reset. Caveat: Note that on microcontrollers featuring an L1 cache, cache reinitialization may cause the runtime value of the variable to change. For devices with an L1 cache and a Memory Protection Unit (MPU), you may choose to use the Memory Protection Unit to create an uncached region of RAM and place the persistent variable into that region.

section ("section-name")

Place the variable into the named section.

For example,

unsigned int dan __attribute__ ((section (".quixote")))

Variable dan will be placed in section .quixote.

The -fdata-sections command line option has no effect on variables defined with a section attribute unless unique_section is also specified.

space(memory-space)

The space attribute can be used to direct the compiler to allocate a variable in a specific memory space. Valid memory spaces are prog for program memory and data for data memory. The data space is the default space for non-const variables.

The prog and data spaces normally correspond to the rom, ram memory regions, respectively, as specified in the default device-specific linker scripts.

This attribute also controls how initialized data is handled. The linker generates an entry in the data-initialization template for the default space(data), but it does not generate an entry for space(prog), since the variable is located in non-volatile memory. Typically, this means that space(data) applies to variables that will be initialized at runtime startup; while space(prog) apply to variables that will be programmed by an in-circuit programmer or a bootloader. For example:
const unsigned int __attribute__((space(prog))) jack = 10;
signed int __attribute__((space(data))) oz = 5;

tcm

The tcm attribute can be applied to data items, where it directs the linker to place the item in the appropriate tightly-coupled memory (TCM) section, that being dtcm, or tcm on those processors where the code and data memory spaces are combined. If no such section is specified in the linker script, this attribute is ignored and a warning is printed. TCM can be used to provide faster and more predictable execution. See 10 Chip-Level Security and Arm® TrustZone® Technology for more details on TCM. This attribute will generally not be supported by other distributions of gcc.

unique_section

Place the variable in a uniquely named section, just as if -fdata-sections had been specified. If the variable also has a section attribute, use that section name as the prefix for generating the unique section name.

For example,

int tin __attribute__ ((section (".ofcatfood"), unique_section)

Variable tin will be placed in section .ofcatfood.

unused

Indicate to the compiler that the variable may not be used. The compiler will not issue a warning for this variable if it is not used.

used

Indicate to the compiler that the object is always used and storage must be allocated for the object, even if the compiler cannot see a reference to it. For example, if inline assembly is the only reference to an object.

weak

The weak attribute causes the declaration to be emitted as a weak symbol. A weak symbol indicates that if a global version of the same symbol is available, that version should be used instead.

When weak is applied to a reference to an external symbol, the symbol is not required for linking. For example:

extern int __attribute__((weak)) s;
int foo() {
  if (&s) return s;  
  return 0; /* possibly some other value */
}

In the above program, if s is not defined by some other module, the program will still link but s will not be given an address. The conditional verifies that s has been defined (and returns its value if it has). Otherwise '0' is returned. There are many uses for this feature, mostly to provide generic code that can link with an optional library.