As everyone should know, underscores in C are not cool, as they cause undefined behavior per 7.1.3:
Yet, they are widely used everywhere. Here are some examples:
* inclusion guards in GLib: ` __G_VARIANT_H__`
* internal Python functions: `_PyUnicode_AsString`
* various macros in APT: `__deprecated`, `__hot`
All of this triggers undefined behavior and is thus uncool. Of course in APT, it’s most stupid, as we do not have any namespace and could thus end up redefining things we should not much more likely then the other two.
But why were those solutions chosen in the first place, and what is the alternative? I cannot answer the first question, but for the second one, the obvious alternative is to use trailing underscores:
* inclusion guards, defined behavior: ` G_VARIANT_H__`
* internal functions, defined behavior: `PyUnicode_AsString_`
* various macros, defined behavior: `deprecated__`, `hot__`
Then there is another class of reserved identifiers with underscores:
Meaning that everything except for parameters, local variables and members of structs/unions that starts with an underscore is reserved. So, if you happen to create a variable _mylibrary_debug_flag
, you trigger undefined behavior as well. And while we’re at it, do not think you can create a type ending in _t
: POSIX reserves all identifiers ending in _t
for its own use.
In summary, whenever you write C and want to be 100% safe of undefined-behavior-because-of-naming, do not start any identifier with an underscore and do not end any identifier with _t
.
Reactions from Mastodon