
Why C's union
and goto
Deserve Respect: Untangling Misconceptions and Maximizing Potential
Memory safety is a critical concern, and the push toward safer languages is understandable. But throwing out established tools isn't always the answer. While new approaches like TrapC aim to enhance C/C++, some propose radical changes, such as removing union
and goto
. To say the complete removal of union
and goto
is outrageous is an understatement. It's harmful and frankly offensive to the language itself.
This article defends these powerful, often misunderstood features, showing how they can be used effectively to write efficient and elegant code. Learn how to leverage union
for memory optimization and goto
for improved error handling and code clarity.
Why the Fuss About Undefined Behavior in C?
C's performance edge comes from its tolerance of undefined behavior. By offloading safety checks to the programmer, the compiler can perform aggressive optimizations. While this can be annoying, those optimizations are specifically useful for real-time software. Sacrificing those optimizations could lead to unacceptable performance hits.
Unveiling the Power of union
in C
For those unfamiliar, union
s are a type construct which holds attributes that share the same memory, the alignment of the union being the largest type in it.
Imagine needing to store different data types in the same memory location. That’s where C union
s shine. Unlike structs, which allocate memory for each member, union
s allow members to share the same memory space. This conserves memory and enables efficient data manipulation.
Consider these examples:
Tagged union
s: Polymorphism in C
By itself, union
s struggle to see any practical application outside of programs that concern themselves with bitwise operations. As it turns out, being able to reinterpret values as other types does offer clever ways of doing bitwise operations. To manage union
s effectively, employ the tagged union
pattern. This involves combining the union
with an enum
that indicates the active type.
Tagged union
s allow leveraging C for type polymorphism. Here's how to define a tagged union
for handling rotations:
Tagged unions are a type of structure that has a name, a tagged union. The tag here is our extra attribute on our wrapper that determines the union's active type. Tagged unions can be seen in various modern languages, most prominently in Rust (where they are referred to as Enums), Zig, and languages that heavily emphasize pattern matching.
Function Macros: Wizardry for Ergonomic C Code
To create instances of tagged unions, function macros are your friend. Here's how you can define macros for the Rotate
type:
Now, creating instances becomes much simpler:
goto
: Not as Evil as They Say
Edsger Dijkstra's "Goto Statement Considered Harmful" paper is often misinterpreted. goto
isn't inherently bad; it's bad when it obscures your program's logic.
goto
becomes bad when it obscures our ability to reason about the dynamic nature of our program, and good when it improves it. In fact, it is so useful for handling exit cases of functions that with one quick lookup, you can see that goto
is found all over the Linux kernel.
goto
for Error Handling and Clean-Up
Consider this snippet from the Linux kernel:
Here, goto
streamlines error handling, ensuring resources are released correctly.
Conclusion
C isn't perfect. But instead of removing powerful tools like union
and goto
, learn to use them effectively. They offer opportunities for clever programmers to create ingenious solutions. Embrace the power and flexibility of C!