22 ms·
On leading underscores and names reserved by the C and C++ languages
- bloak 4y ago"It may come as a surprise that the C language reserves identifiers like strong, island, and together, but it does." Yes, I would guess that a large proportion of C programmers are not familiar with those rules. Is there a way of getting GCC or LLVM to warn about it?
- beached_whale 4y agoclang recently added `-Wreserved-identifier`, I think in v14 or v15. I may be slightly off in how it is said, but it’s there. Not sure about gcc
- rwmj 4y agoThe GCC bug's only been around for 11 years: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51437 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51437
- coldpie 4y agoStrong evidence that these rules don't actually matter and can be disregarded.
- rwmj 4y agoFor sure! I've been writing C for about 40 years and didn't know that such innocent identifiers as "total" were reserved.
- raverbashing 4y agoIt's more like "disregard them at your own risk" The issue here is not GCC/Clang. It's developers You risk having a name collision if you define a strfoom in your code and then later the C committee decides to add that to string.h
- Aardwolf 4y agoThe issue is not developers, but disallowing the patterns is[a-z].*, to[a-z].*, str[a-z].* and others. Why would anyone do this to a programming language? It's a stupid decision to reserve those and it ruins the usability of the language by arbitrarily disallowing many common words that have nothing to do with the intended feature. Even if you don't export names like this directly, having the name of your library or company (as prefix for all exported names) start with those common combinations is likely as well, so now you got to avoid certain library or company names. If this is only since C11, then I'm even more baffled, since I could somewhat see how such thing could happen in the 1970s when there were limits and the language was brand new and not known to be popular, but in 2011 doing this makes no sense whatsoever. I hope this is limited to C11 and will never happen in C++.
- zokier 4y agoRoot problem is the lack of namespaces in C, making collisions inevitable and painful to deal with
- flohofwoe 4y agoC doesn't even need namespaces for this, a simple stdc_ prefix for stdlib functions and types would also work (see C23 stdbit.h, I hope this won't be an outlier).
- im3w1l 4y agoWith proper namespaces you can import stuff so you don't have to prefix with the namespace every time.
- flohofwoe 4y agoYes, but we can't simply port C++ namespaces over because this requires symbol name mangling. C could be using 'namespace prefixes' instead with something like 'usingprefix stdc_', this wouldn't require changes to the symbol format, and would provide most of the features of C++ namespaces.
- jerf 4y agoI mean, de facto, if Windows isn't good at it, at the very least compilers will have a "never mind ignore this" option if they even do start enforcing them. And while Raymond Chen knows Windows and can speak to it, I'd bet the Linux kernel has plenty of violations of this, and it's the same thing; no future C compilers are going to invalidate that no matter what some C committee somewhere says.
- kps 4y agoAlso, clang-tidy has `bugprone-reserved-identifier` https://clang.llvm.org/extra/clang-tidy/checks/bugprone/reserved-identifier.html https://clang.llvm.org/extra/clang-tidy/checks/bugprone/rese...
- planede 4y agoIt only checks for the ones starting with underscore. > This check does not (yet) check for other reserved names, e.g. macro names identical to language keywords, and names specifically reserved by language standards, e.g. C++ ‘zombie names’ and C future library directions.
- peterfirefly 4y agoAnd it complains about this: #define _POSIX_SOURCE which is sometimes needed before the #include's to get access to nice, modern library functions that are, say, thread-safe.
- marssaxman 4y agoAfter thirty-some-odd years writing C, this is the first I have ever heard of it. I wonder how many times I have inadvertently broken those rules.
- deleted 4y ago[deleted]
- omgmajk 4y agoI hear Dave (Dave's Garage) talk about Raymond in a lot of his episodes on youtube and I get the feeling this guy is a legend.
- Kwpolska 4y agoYes, Raymond is a legend, and it’s really worth it to dig into the blog archives. (Dave, however, has a really annoying presentation style, and is so overrated.)
- danybittel 4y agoSo C did pre-emptively reserve certain words? Like island, strong, together.. I wonder if that paid off in some cases? Or to ask differently, if one would design a new programming language (now), would you consider reserving words in advance?
- kzrdude 4y agoIf you reserve something in a new language, you'd properly make it an error to use it.
- klodolph 4y agoES5 had "future reserved words" including class, const, export, import, and let.
- livrem 4y agoJava has goto and const as reserved keywords. Source: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_k...
- kps 4y agoC orignally had `entry` as a reserved work (from Fortran 77, where a function could have multiple entry points).
- WorldMaker 4y agoThe ES5 case is interesting because most of that list of "future reserved words" was a list of reserved words in ES4 "The Lost Version". That list also included fun things still not used like private, public, abstract, package, byte, int, volatile, synchronized.
- WorldMaker 4y agoOne additional fun thing to note is that despite "private" already being reserved as a keyword TC-39 when they did somewhat recently add private fields to classes a few years back decided on "hash names" over the private keyword. class Example { #privateFieldName } Rather than: class Example { private privateFieldName } The debate on that was pretty interesting.
- throwaay2495343 4y ago[flagged]
- kzrdude 4y agoThen after looking into the C standard, POSIX further defines C identifiers for itself. That includes `_t` in type names! It's a rule so far from enforcement in reality that it is hard to take seriously.
- ryanianian 4y agoThe trailing _t is reserved, and I didn't know that for many years. I learned of it only after an interview candidate pointed it out as a gotcha in my question prompt. They got bonus points, and I learned something. I wonder why compilers or static analyzers don't complain about these things more often?
- flohofwoe 4y ago> I wonder why compilers or static analyzers don't complain about these things more often? Because it's not the C compiler's business to care about POSIX. POSIX and the C standard are different things. If you're writing code against the Windows APIs, POSIX isn't relevant for instance, and you need to be more concerned about colliding with type names or defines from the Windows API headers, and those are all over the place anyway. ...and besides: that rule is entirely pointless in reality, either your type names collide with POSIX types from headers you are including (in that case you're getting a compiler error anyway), or they don't collide, and in that case all is good.
- never_inline 4y ago> besides: that rule is entirely pointless in reality I think it means: a library author cannot name some type epoch_t, because POSIX may introduce an epoch_t in the next revision, and suddenly some code may fail to compile.
- flohofwoe 4y agoYes, but this sort of problem exists with other 'standard APIs' too which change much more frequently than POSIX.
- Aardwolf 4y ago> We’re trying to do better for new headers, but not everyone has gotten the memo. And memo appears to be one of the disallowed variable names in C11, given the mem[a-z].* pattern
- coreyp_1 4y agoI got bit by this last night (C++), and had no idea that it was a thing. What a timely post!
- chappar 4y agoIt would be interesting to hear more about this!
- PreInternet01 4y ago> It may come as a surprise that the C language reserves identifiers like strong, island, and together, but it does OK, I know it's only an offhand remark in a blog post, but now I'm going to have to spend significant energy on: 1. Finding where these identifiers are reserved, exactly, because obvious sources like https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html https://pubs.opengroup.org/onlinepubs/9699919799/functions/V... don't seem to include them? 2. Trying to come up with the intended usage for these identifiers (`island` I imagine, might be a scope: only accessible to other identifiers on the same island? oh my...)
- peff 4y agoOn the page you linked, you can see that `ctype.h` reserves all prefixes of `is[a-z]` and `to[a-z]`, and `string.h` reserves `str[a-z]`. These come from the C standard (in C99, it's 7.26 "Future Library Directions"), though I don't think they use the word "reserved" there.
- aw1621107 4y agoThe "reserved" bit is from section 7.1.3: > Each header declares or defines all identifiers listed in its associated subclause, and optionally declares or defines identifiers listed in its associated future library directions subclause and identifiers which are always reserved either for any use or for use as file scope identifiers.
- AdamH12113 4y agoHe says where they come from -- section 7.31 of the C11 standard[1]. For example, in 7.31.12: > Function names that begin with str and a lowercase letter may be added to the declarations in the <stdlib.h> header. Or 7.31.13: > Function names that begin with str, mem, or wcs and a lowercase letter may be added to the declarations in the <string.h> header. So according to the standard, if your code #includes string.h, it may conflict with a future version of the standard if you use names like "strong" or "memorize". This is extraordinarily unlikely, though. [1] https://port70.net/~nsz/c/c11/n1570.html#7.31 https://port70.net/~nsz/c/c11/n1570.html#7.31
- deleted 4y ago
- moloch-hai 4y agoHe fails to note that a pair of underscores appearing anywhere in a name is reserved, not just in leading position. Also, a leading underscore followed by a capital letter, or other reserved name, is absolutely allowed in implementation headers -- even in non-standard headers. It is bad practice only because somebody else's compiler (e.g. Clang) might be obliged to read those headers someday, and have invented its own meaning for it.
- mmoll 4y agoAfaik, underscore-underscore anywhere in a name is reserved in C++ only. C only reserves names starting with underscore-underscore. And yes, you can get away with using these identifiers, but you could almost never be certain that you did.
- moloch-hai 4y agoMicrosoft could be absolutely, utterly, undeniably certain it got away with using names reserved to the implementation in its implementation. Arguably some headers are not part of the implementation, because they don't come with MSVS. But that is a matter of packaging, which the Standard does not cover. And, only C++ is of any interest, here. Microsoft never gave a damn about C, and any name reserved in C is also reserved in C++.
- Scubabear68 4y agoOn a tangent, but this is what makes Python look so ugly to me, the required use of double underscores for things like equals is extremely jarring. I have very slowly come to appreciate it as a language, but visually it will always be ugly to me because of clashes like this with other languages.
- Genbox 4y agoI get the same feeling when looking at SIMD code. > const __m256i in = _mm256_loadu_si256((const __m256i*)ptr);
- AshamedCaptain 4y agoyou are supposed to use a typedef, not to do that. It's like complaining you have to use _Bool all over the code. Include stdbool...
- Narishma 4y agoIt's the reason I prefer to write inline assembly, or even external assembly, for SIMD code rather than use intrinsics. Much easier to read.
- chjj 4y agoI tried to decipher all of the rules surrounding reserved identifiers once. It was surprisingly tricky. https://gist.github.com/chjj/d0c1218e473bbb6d8f9e2224c583e2db https://gist.github.com/chjj/d0c1218e473bbb6d8f9e2224c583e2d...
- McKayDavis 4y agoLike
- gernb 4y agoI know it's a tradeoff but I think I fall on the side of I wish the language I was writing in required `this` or `self` for members/properties. C++ foo = bar \* 2; Are foo and bar local variables or members of some instance? vs Python self.foo = self.bar \* 2 100% clear. No naming convention needed. I bring this up because `_foo` for members is a naming convention that wouldn't be needed in a language that required `self` or `this` That said, I get that maybe refactoring some code from standalone function to class method is easier if you don't have to change the code as much but I'd be curious how often that's a net win.
- TillE 4y agoWhen writing idiomatic C++, you typically end up with mostly stuff like impl->foo anyway. The pimpl pattern is sort of a weird artifact of how the compiler works, but it generally works out as a smart way to structure your code.
- BenFrantzDale 4y agoIt really depends. I used PImpl today but it’s the rare exception. Between small inlinable classes and abstract base classes, there are lots of ways work. But that’s the beauty of C++: there are lots of ways to solve problems!
- mhh__ 4y agoAs a language design point it's also saying that (this simple modification to C++) void add(const this, int x) Is more readable than (IMO) void add(int x) const
- kccqzy 4y agoYou may like the "deducing this" proposal: http://wg21.link/P0847 http://wg21.link/P0847 (Scroll down to the "proposed syntax" section.)
- TeMPOraL 4y agoMight as well just always spell out the hidden "this" argument. Then all methods would look just like regular functions, allowing to simplify the language syntax and the standard, making it more concise and consistent, without sacrificing any functionality.
- int_19h 4y agoIn C++ especially, respecting the rules on underscores is important because so much of stdlib is header-only, meaning lots of inline code that's exposed to shenanigans with identifiers used in it. For example, if you #define foo 123, and some inline function has a local named "foo", there's going to be a problem. This is why, when you look at standard C++ headers in most implementations, all identifiers, even locals, tend to be named _Like __this. And stdlib may also need to define its own internal macros (as there's a lot of repeated verbiage), which also follow this name pattern. So if you disregard the fact that those are reserved, it might build, but even a minor update of your implementation that e.g. adds a new local to some obscure standard function can break it, never mind a new version of the C++ standard.
- jhoechtl 4y ago> Windows header files have historically not been conscientious about avoiding these reserved names. We’re trying to do better for new headers, but not everyone has gotten the memo. Love that tone
- pjmlp 4y agoWindows 2000 introduced the concept of application manifests, where executables get a mini XML file for application specific settings instead of storing them into the registry. They also allow for registration free COM components. To this day many Microsoft teams still haven't gotten the memo.
- TeMPOraL 4y agoI'm not sure if they provided adequate tooling for the former. They definitely didn't provide adequate documentation for the latter. Or maybe they did - back when MSDN was actually well-organized and somewhat complete-ish (and shipped on optical disks or otherwise downloadable!), I was too young to make much use of it. Now, that wealth of knowledge is mostly gone, and external links to it don't resolve.
- pjmlp 4y agoNaturally it is documented, otherwise how would I know about it without ever being a Microsoft employee? These are the current locations for them, https://learn.microsoft.com/en-us/windows/win32/sbscs/creating-registration-free-com-objects https://learn.microsoft.com/en-us/windows/win32/sbscs/creati... https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference https://learn.microsoft.com/en-us/windows/win32/sbscs/manife... https://learn.microsoft.com/en-us/windows/win32/sbscs/isolated-applications?source=recommendations https://learn.microsoft.com/en-us/windows/win32/sbscs/isolat... https://learn.microsoft.com/en-us/windows/win32/sbscs/authoring-state-storage-for-side-by-side-assemblies https://learn.microsoft.com/en-us/windows/win32/sbscs/author... (see last bullet points regarding not to use the registry as best practice) The problem as usual, is lack of education on the matter, and willingness to change how people work. I stand corrected on one point though, it has been a long time and actually it was only introduced on Windows XP and Server 2003, not Windows 2000.
- ninkendo 4y agoRaymond Chen is worth his salary at Microsoft if the only thing he does is blog. His blog has been so consistently good, for so long, posting so often, it gives me imposter syndrome thinking about how he could possibly have a day job on top of it.
- agumonkey 4y agoHe also strikes that great balance between fun to read, low level and precise. Thankful for this articles, always a reflex click :)
- mc32 4y agoHim and Russinovich --before he joined MS.
- richsu-ca 4y ago"before" :)
- shultays 4y agoAlso whenever I have a question, it feels like he has the answer. No matter how specific the question is
- ilyt 4y agoWell, I'd imagine the day job is why the blog is so good.
- nikanj 4y agoAnd every year or so Microsoft wrecks all links to his blog, so linking to old articles never works properly. It’s highly ironic that the blog talking about backwards compatibility moves urls constantly
- deleted 4y ago[deleted]
- int_19h 4y agoThere was also Michael Kaplan, who had a similarly informative and in-depth blog "Sorting it all out" about localization, text encodings, keyboard layouts etc in Windows. In fact, Raymond Chen specifically recommended him on these topics: https://devblogs.microsoft.com/oldnewthing/20041217-00/?p=36963 https://devblogs.microsoft.com/oldnewthing/20041217-00/?p=36... Unfortunately, Microsoft didn't exactly treat him kindly [1] in the end. And to add insult to injury, his blog was completely wiped. There are some archives around, but I haven't seen one that retained the images, which often makes the posts incomprehensible, unfortunately. [1] https://vsubhash.wordpress.com/2017/04/17/rip-michael-j-kaplan/ https://vsubhash.wordpress.com/2017/04/17/rip-michael-j-kapl...
- zabzonk 4y agoreally, avoid underscores altogether - they are very horrible. even people that know that there are exclusion rules for them don't really know what the rules are. and if you get things wrong, the error messages your compiler gives you will be incomprehensible. so, just don't use them - why would you?
- cesaref 4y agoI've never seen leading underscores in classes. I've seen trailing underscores, and the old m_ prefix, but never a plain _. I was surprised by C++11 having additional prefixes it has reserved. I'm now also wondering whether there is a clang/gcc option to warn about such things, as although I know we don't currently have any issues in our code base (as in, it compiles and works) I don't really want to publish a public API and have to revisit it because of such a conflict in C++29 or whatever
- zabzonk 4y agosome underscores have been reserved in certain situations in user code from ansi c and onwards - there is simply no need to use them. trailing underscores will work but why bother? they are difficult to read and difficult to type.
- colanderman 4y agoTrailing underscores are my go to for resolving conflicts with keywords. It's a much more consistent and trivial to remember rule than random misspellings or synonyms of keywords (casts side-eye to `klazz`).
- zabzonk 4y agodon't understand this at all - why would you want to use a keyword as a name, and the last bit of the comment makes no sense at all.
- 4y ago