The Best GCC Tips and Tricks You Must Know
The Hitchhiker Guide to GNU C
Being an embedded developer for so many years, I’ve spend more time with GCC than any other tool, and getting the most of it have been a pleasant journey.
The following is condensing my favorites GCC tricks and tips in no particular order, and will get updated over time and suggestions.
If portability matters to you, you should probably look elsewhere. But if you’re a Linux developer, a creative Arduino maker, or an embedded developer there’s a chance that GCC is the only targeted compiler. So, why not taking the convenient road? After all, the Linux Kernel source code isn’t portable, and nobody cares.
Variable Cleanup Function
The cleanup
variable attribute runs a function when the variable goes out of scope. The function will be passed a pointer to the variable as a convenience:
One of my favorite usage of the cleanup
attribute is to automatically release a lock within a method accessing a mutually exclusive resource:
Weak Function
The weak
function attribute causes the declaration to be emitted as a weak symbol instead of global, which makes it overridable:
As a nice side-effect, undefined weak functions are evaluating to null
and could come in handy, for example, to implement some optional user-defined hooks into your library:
Finally, the weak
function attribute pairs extremely well with alias
to declare a default implementation:
Automatic Type Inference
GNU C introduced the __auto_type
keyword. Maybe you’re already aware of typeof
to refer to the type of an expression:
A typeof
construct can be used anywhere a typedef
name can be used: you can use it in a declaration, in a cast, or inside of sizeof
or typeof
.
In GNU C, similar to the C++11 auto
keyword, you may also declare the type of a variable as __auto_type
:
The macro above operates on any arithmetic type and evaluates each of its arguments only once.
The advantage of
__auto_type
in the macro above is that each argument to the macro appears only when expanded, preventing the size of the macro expansion growing exponentially when calls to such macros are nested inside arguments of such macros. Moreover, if the argument to the macro type has variably modified type, it is evaluated only once when using__auto_type
, but twice iftypeof
is used.
Wrapper Function
The GNU linker --wrap=symbol
option provides a wrapper function for a given symbol. The wrapper function should be called __wrap_symbol
and the wrapped function can be called through __real_symbol
:
Case Ranges
GCC allows range of consecutive values to be specified in a single case
label:
Designated Initializers
ISO C99 relaxed elements initialization by allowing array indices or structure field names to be specified during initialization. GNU C allows this extension in C90 mode as well, along with range-initialization of arrays:
Cast to Union
A cast to union type is similar to other casts, except that the type specified is a union type:
A cast to union is actually a constructor, not a cast, and hence does not yield an lvalue like normal casts (see compound literals).
Unnamed Structure Fields
Introduced in ISO C11, unnamed structure and union fields were supported well before by GCC:
One of the most straightforward usage of such feature is decomposition which also pairs extremely well with cast-to-union and bit fields. Please note that the examples below support little-endian byte order only for brevity:
Constructor Function
The constructor
function attribute causes the function to be called automatically before the execution enters main()
. Similarly, the destructor
attribute causes the function to be called automatically after main()
completes or exit()
is called:
You may provide an optional integer priority to control the order in which constructor
and destructor
functions are run. A constructor with a smaller priority number runs before a constructor with a larger priority number; the opposite relationship holds for destructors:
Compound Literals
A compound literal designates an unnamed object: its value is an object of the type specified in the cast, it’s an lvalue. Supported in ISO C99, GCC also supports compound literals in C90 mode:
Nested Functions
A nested function is a function defined inside another function. Thanks to lexical scoping, the nested function can access all the variables of the containing function that are visible at the point of the definition:
Zero Length Arrays
Zero-length arrays are allowed in GNU C and are really useful as the last element of a structure that is an header to a variable-length object:
Beware that non-empty initialization of zero-length arrays is treated like excess elements and are ignored: as an alternative (and convenience), GCC allows static initialization of flexible array member:
Arrays of Variable Length
Variable-length arrays are allowed in ISO C99 and GCC accepts them in C90 mode as an extension:
Support for offsetof (and beyond)
The macro offsetof
evaluates to the offset (in bytes) of a given member within a struct or union type. The offsetof
macro takes two parameters, the first being a structure name, and the second being the name of a member within the structure:
A real-life example of the offsetof
macro would be the Linux Kernel container_of
macro:
Transparent Union
The transparent_union
variable attribute, when 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: the argument corresponding to a transparent union type can be of any type in the union; no cast is required:
Stringizing
When a macro parameter is used with a leading #
, the preprocessor replaces it with the literal text of the actual argument, converted to a string constant:
Beware that stringizing the result of the expansion of a macro argument requires two levels of macros:
Concatenation
Merging two tokens into one while expanding macros can be useful. The ##
preprocessing operator performs token concatenation:
I’d recommend to use some helpers to include for re-use:
Repeat Macro
Thanks to the concatenation preprocessing operator, a REPEAT
helper macro can be written to achieve repetitive constructs:
Poor Man’s Templating
The concatenation preprocessing operator, along with #include
, allows some sort of basic templating:
Compile-Time Assertions
C11 introduced the _Static_assert
keyword for compile-time assertions but if you’re running GCC 4.5 or below, here’s a workaround:
That’s all for now! The above article has been written with ❤, feel free to share and don’t forget to clap if you liked it!