This is mainly for Andy Finnell on Twitter, who wonders why some of us avoid naming variables
I pointed out that there is a function in standard C named
index, and this causes one of two problems: If you declare a variable named
index, you have shadowed the function and should get a warning for that; if you fail to declare the variable, you pass the pointer to the
index function as your array index, which is probably not what you intended.
I say “should” there because, as he noted in his response, the shadowed-name warning is off by default. You should turn it on, because it catches bugs. In fact, the
index bug is one that it can prevent.
Suppose you do name a variable
index, and either you don’t have the shadowed-name warning turned on or you ignore it. You initialize the variable with an index, but don’t otherwise assign to it. Then, you attempt to access an object in an array by this index.
All well and good so far.
index is a variable, so everything works as intended.
But then, one of several things happens:
- You comment out both the declaration and the usage of
index, for whatever reason, but then you uncomment the usage but forget to uncomment the declaration.
- You update and/or merge in your version-control system, or otherwise apply one or more diffs. Usually, this works, but today isn’t your lucky day: The merge breaks your source code. Perhaps it introduces conflicts, and you resolve them incorrectly. Or maybe it breaks the code silently (e.g., by merging in another branch’s division of this function into two).
- You move the code to another location, but you forget to move half of it, or you move one half and delete another, forgetting that the declaration of
index was in the code you deleted.
You had a variable named
index, but now you don’t—but the
index function is always there*. Since there is something named
index, your code compiles. It’s the wrong type, so you’ll get a warning, but maybe you don’t notice it.
Then you run the code and it crashes. Why? Because you passed a function as the index into an array.
In the worst possible case, it was #2 and you weren’t aware that this code was affected. Maybe you’d been working on something else. Anyway, since you hadn’t been working on the now-broken code, you aren’t testing it**, so you don’t know that it’s now broken.
So you ship it. You ship this
index-way-out-of-range crasher. And then your user runs the code and gets the crash.
This isn’t theoretical. I’ve had this happen more than once (fortunately, not in the hands of a user). It’s one reason why I turn on the shadowed-name warning and “Treat Warnings as Errors”, and it’s the reason why I never use
index as a variable name.
UPDATE 2009-12-05: To clarify, this problem does not affect C arrays, as C does not allow you to use a pointer in an array subscript. It mainly affects higher-level array interfaces, such as Cocoa’s NSArray.
* Assuming that, directly or indirectly, you’ve included string.h. If you’re using Cocoa, you have (Core Foundation includes it). ↶
** Unless, of course, you have automated test cases covering this code, and you run those. ↶