{"id":107685,"date":"2023-01-09T07:00:00","date_gmt":"2023-01-09T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=107685"},"modified":"2024-12-14T07:41:23","modified_gmt":"2024-12-14T15:41:23","slug":"20230109-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230109-00\/?p=107685","title":{"rendered":"On leading underscores and names reserved by the C and C++ languages"},"content":{"rendered":"<p>The C and C++ languages reserve certain categories of names for the implementation, which means that you cannot use them in your own code. Some are reserved unconditionally, precluding their use for variable names, parameter names, classes, methods, macros, whatever. Others are reserved only in certain contexts.<\/p>\n<p>The rules for C++ are collected in <a href=\"https:\/\/timsong-cpp.github.io\/cppwp\/lex.name#3\"> the <b>[lex.name]<\/b> chapter<\/a>. The rules for C <a href=\"https:\/\/docs.microsoft.com\/en-us\/cpp\/c-language\/c-identifiers?view=msvc-170\"> happen to match the C++ rules<\/a> for the most part, (section 7.1.3 &#8220;<a href=\"https:\/\/www.open-std.org\/jtc1\/sc22\/wg14\/www\/docs\/n1570.pdf\">Reserved identifiers<\/a>&#8220;), so that makes things easier to remember.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Pattern<\/th>\n<th>Conditions<\/th>\n<\/tr>\n<tr>\n<td>Begins with two underscores<\/td>\n<td>Reserved<\/td>\n<\/tr>\n<tr>\n<td>Begins with underscore and uppercase letter<\/td>\n<td>Reserved<\/td>\n<\/tr>\n<tr>\n<td>Begins with underscore and something else<\/td>\n<td>Reserved in global scope (includes macros)<\/td>\n<\/tr>\n<tr>\n<td>Contains two consecutive underscores<\/td>\n<td>Reserved in C++ (but okay in C)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Note that a popular convention of prefixing private members with an underscore runs afoul of these rules if the member name begins with an uppercase letter.<\/p>\n<pre>class Widget\r\n{\r\npublic:\r\n    Widget();\r\n\r\nprivate:\r\n    int _size; \/\/ okay\r\n    void _Toggle(); \/\/ not okay\r\n};\r\n<\/pre>\n<p>The C language does not have namespaces, so it also must reserve names in the global namespace for future expansion. Some names may not be used by symbols with external linkage. You can use them for type names, enumeration members, local variables, and functions or global variables declared with static storage class, but not for extern functions or extern global variables.<\/p>\n<pre>\/\/ Not allowed: Identifier with external linkage\r\n\/\/ beginning with \"str\" and a lowercase letter.\r\nint strategy;\r\nvoid strafe() { \/* ... *\/ }\r\n\r\n\/\/ Allowed: Identifier with internal linkage beginning\r\n\/\/ with \"str\" and a lowercase letter.\r\nstatic int strawberry;\r\nstatic void stream_video() { \/* ... *\/ }\r\n<\/pre>\n<p>Furthermore, if you include the corresponding header file, the names are permitted to be shadowed by function-like macros. This means that if you intend to use a reserved name for something without external linkage, you must first <code>#undef<\/code> it or enclose the name in parentheses to prevent it from being treated as a macro.<\/p>\n<pre>\/\/ Including this header may result in the definition\r\n\/\/ of a function-like macro named \"strategy\".\r\n#include &lt;string.h&gt;\r\n\r\n\/\/ Must enclose in parentheses to prevent misinterpretation\r\n\/\/ as function-like macro.\r\nstatic void (strategy)();\r\n<\/pre>\n<p>As of C11, identifiers matching the following regular expressions may not be used for symbols with external linkage. (The list is given in section 7.31: &#8220;Future library directions&#8221;.) There are also reserved names for type definitions and macros, but I won&#8217;t list them here.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Pattern<\/th>\n<th>Header<\/th>\n<\/tr>\n<tr>\n<td><code>cerfc?[fl]?<\/code>, <code>cexp2[fl]?<\/code>,<br \/>\n<code>cexpm1[fl]?<\/code>, <code>clog1[0p][fl]?<\/code>,<br \/>\n<code>clog2[fl]?<\/code>, <code>c[lt]gamma[fl]?<\/code><\/td>\n<td><code>complex.h<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>is[a-z].*<\/code>, <code>to[a-z].*<\/code><\/td>\n<td><code>ctype.h<\/code>, <code>wctype.h<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>atomic_[a-z].*<\/code><\/td>\n<td><code>stdatomic.h<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>str[a-z].*<\/code><\/td>\n<td><code>stdlib.h<\/code>, <code>string.h<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>mem[a-z].*<\/code><\/td>\n<td><code>string.h<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>wcs[a-z].*<\/code><\/td>\n<td><code>string.h<\/code>, <code>wchar.h<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>cnd_[a-z].*<\/code>, <code>mtx_[a-z].*<\/code>,<br \/>\n<code>thrd_[a-z].*<\/code>, <code>tss_[a-z].*<\/code><\/td>\n<td><code>thread.h<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>It may come as a surprise that the C language reserves identifiers like <code>strong<\/code>, <code>island<\/code>, and <code>together<\/code>, but it does.<\/p>\n<p><b>Bonus chatter<\/b>: Windows header files have historically not been conscientious about avoiding these reserved names. We&#8217;re trying to do better for new headers, but not everyone has gotten the memo.<\/p>\n<p><b>Update<\/b>: Added special &#8220;internal double-underscore&#8221; rule.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The rules laid out.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-107685","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>The rules laid out.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/107685","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=107685"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/107685\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=107685"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=107685"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=107685"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}