Search code examples
cnaming-conventionsnaming

Unreserved names


The C language has a set of outright reserved keywords. However, there is a much larger set of identifiers that are reserved or semi-reserved, whose use is at least strongly not recommended because they are used by the standard library or various system headers, or may be so used in future, etc; there is a comprehensive though not exhaustive list of those here: https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html

The set of such names is much too large to be feasible to enumerate.

Looking at it from the perspective of using C as a compilation target, I'm looking for the reverse: a set of names I can generate, that are guaranteed to be not reserved, to be free for application use.

Clearly this requirement could be effectively met as far as it goes by prepending a UUID to every name, but there is an additional requirement that the generated code be as amenable as possible to eyeball debugging, so the namespace should be as simple as possible, e.g. if all names are to have a common prefix, that prefix should be as short as possible.

What's the simplest way to characterize a set of names that are guaranteed, or failing that highly likely, to be free for application use? For example, would it be safe to use arbitrary names prefixed with x_ or suchlike?


Solution

  • Most C libraries provide feature-selection macros, which allow you to specify which version of the interface you are using. If you set _POSIX_C_SOURCE and _XOPEN_SOURCE before including any system headers on Linux or UNIX, your system libraries will not declare any identifiers that future versions of UNIX might define. (In theory, setting either one by itself should suffice, but it’s good defensive coding to set both, as this will prevent one or the other from being set inconsistently by someone else.) On Windows, you would declare NTDDI_VERSION and _WIN32_WINNT.

    The C Standard Library only provides feature-test macros, not macros that let you choose an interface, but compliers support a flag such as -std=c20, and you should set this in your build scripts. This should disable any new keywords or identifiers that get added to the language in the future.

    If you depend on a specific version of a library, and are worried that changes to its header files could break your code, you can put a copy of the headers (and to be absolutely certain, the library itself) in your project tree. If the library is open-source, making a note of which version you used should let anyone else download the right version. Otherwise, you’re at the mercy of its maintainers.

    Do not declare _BSD_SOURCE or _GNU_SOURCE if this is a concern for you! Linux headers without glibc bindings, such as <linux/module.h>, generally don’t have this kind of versioning.

    Some languages have much more robust solutions for this, such as cabal and stack for Haskell or cargo for Rust.