C/C++ defer for the rest of us

By now, most programmers are familiar with the defer mechanism, at least in the context of Go code. Many also recognize that it’s a “nice-to-have feature” that hasn’t been implemented by mainstream C compilers.

ISO C23 has no defer. But of course, GCC and Clang have all the necessary C23 features and compiler extensions to implement defer as a simple macro. One defer C23 macro is described in Jens Gustedt’s article as a “simple defer, ready to use” solution. This macro works with both GCC and Clang right now in March 2025.

Here is GO lang defer, simply explained in the GO documentation

A defer statement defers the execution of a function until the surrounding function returns.
The deferred call’s arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.

That is simple and exactly what Jens’ “simple defer, ready to use” accomplishes. A convincing way to demonstrate this would be to create a Godbolt example using the code from that article. Here is the Godbolt sample, with just the main function pasted below.

The output is:

Simple to implement for GCC/Clang enthusiasts. Importantly, defer {} blocks are executed in reverse order, with the last one running first. If you consistently use the defer mechanism in your GCC/Clang C23 code, the benefits are clear: your code will be safer and more resilient.

But, what about the rest of us?

Who are “us”? We are those using Visual Studio and Microsoft Visual C++ (MSVC). We need a simple, MSVC-friendly solution, even if it’s not perfect. And here it is without further explanation:

It is a known “trick” of using the for () loop in a macro and its inherent behaviour. Here is a short explanation of how that works.

The first thing to notice is beginend and defer arguments are function calls. But: not executed because they are macro arguments. They are executed when it is their turn in the for loop “header”. Thus the following code is possible:

Macro is just a text replacement mechanism. Ditto, the above is translated into this:

Notice the comma operators in the for() above:

The make_() function gets called, and then the comma operator is used with 0 appearing after the comma. This means the entire expression evaluates to 0, which becomes the value of the int _i_123 variable.

The for() {} body runs while _i_123 is 0. When it becomes 1, this part is executed immediately after the block ends:

_i_123 becomes 1, and then after the comma operator, that free_ gets called. And defer  macro uses the same “trick”, but with no beginning argument.

Here is a simple usage example

Yes, that also is not a defer {}  syntax that will eventually come with (apparently) the next ISO C after 23. Our required syntax is:

beginend ( block_begin_expression , block_end_expression )  { /*  adjacent code block */ }

defer ( block_end_expression )  { /* adjacent code block */ }

That “adjacent block” is just a for block coming right after.

 Conclusion

One could argue that this is merely an “illusion of deferring.” I might agree, but the important point is that it works “everywhere” and is currently workable (as of Q2 2025) also with Microsoft Visual C++. It’s worth noting that defer is not part of the ISO C23 standard. However, it can be easily implemented as a macro without using GCC/CLANG. And yes, this defer implementation works with C++ as well. (My Microsoft C/C++ compiler version, right now, is 19.43.34808 for x86)


I last saw it here https://youtu.be/QpAhX-gsHMs

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.