GNU Compiler Collection - gcc/g++

__attribute__

__attribute__ is a keyword introduced by GCC. It is regarded as an extension of a language. It helps the compiler optimize calls, check code more carefully for correctness, control memory placement and code generation options.

Syntax

1
__attribute__ ((attribute-list))

where an attribute-list is a possibly empty comma-separated sequence of attributes. Say:

1
static void _init( void ) __attribute__((constructor));

Categories

Let’s say to specify an attribute of variables.

1
2
extern __thread struct _glapi_table * _glapi_tls_Dispatch
__attribute__((tls_model("initial-exec")));

where the tls_model attribute sets thread-local storage model of a particular thread variable, overriding -ftls-model= command-line switch on a per-variable basis. The tls_model argument should be one of global-dynamic, local-dynamic, initial-exec, or local-exec.

Visibility

1
__attribute__((visibility("default")));

this attribute involves with the visibility of exported symbols in a shared object, overriding -fvisibility=hidden command-line option during the compilation. The visibility argument should be one of default, hidden, internal, or protected.

内置宏

编译器会预定义许多宏,尤其在交叉编译时,不同的工具链编译器会定义不同的宏。例如:

  • aarch64
  • __ARM_ARCH_7A
  • __ARM_ARCH_8A

如果使用armv7的工具链,那么只有__ARM_ARCH_7A会被定义,而如果使用armv8的工具链,那么只有__ARM_ARCH_8A会被定义。但以上两个编译器都会定义__aarch64__.

How to Check Macros Predefined by Compiler

1
aarch64-linux-gnu-gcc -march=armv8-a -E -dM - < /dev/null
  • -Egcc的一个common option, 指示编译器只做预处理
  • -d<letters>gcc的一个common option, 打开由字母指定的compiler pass的dump
    • -dM 打印预处理阶段所有的宏#define, 包括预定义宏。
    • -dD 功能和-dM类似,但它不包含预定义宏,而且它同时输出#define和预处理结果。
    • -dN 功能和-dD类似,但只输出宏名,不展开宏。
    • -dI 除了预处理结果外,还输出#include.
    • -dU 功能和-dD类似,但只输出那些被展开的宏或在预处理中被#if, #ifndef测试过的宏。

__builtin_offsetof

  • C/C++ 宏 offsetof 包含在头文件 stddef.h

内置函数

__builtin_clz

int __builtin_clz(unsigned int x);

返回一个数的高位端的 0 的个数

原子操作函数族

  • type __atomic_add_fetch(type *ptr, type val, int memorder)

以原子方式给 ptr 指向的内存值加上 val, 并返回 ptr 指向内存加完后的值。它与 GCC 的 __sync_add_and_fetch() 有何区别呢? 唯一的区别是 __atomic_add_fetch 更新。

  • bool __atomic_compare_exchange_n(type *ptr, type *expected, type desired, bool weak, int success_memorder, int failure_memorder)

原子 CAS 操作:

1
2
3
4
if (*ptr == *expected); then
*ptr = desired // read-modify-write
else
*expected = *ptr // read

type __sync_val_compare_and_swap (type *ptr, type oldval, type newval, ...)

内置的原子比较和交换操作,也就是说,如果 *ptr 的当前值是 oldval, 则把 newval 写入 *ptr, 并且返回写入前的 *ptr 值。

与编译器相关的 keywords

volatile vs. register

volatile register
type qualifier storage class
force (compiler) hint (compiler)
latency fast
OK for global variables NOT for global variables