I learned to program in C nearly 30 years ago. When support for the const qualifier appeared in compilers some 10 years later, I learned to place it as most programmers do: to the immediate left of the type that it modifies. That is, when I wanted to declare p as a pointer to a constant character, I wrote the declaration as:
const char *p;
as just about everyone else did.
As I grew to understand the const qualifier better, I started to encourage other programmers to use it, which I did by using const whenever appropriate in my writing and in my lectures, and I was not alone. Other writers and speakers were using const as well. Still, many programmers seemed less than enthusiastic about using const .
I started asking programmers why they were reluctant to use const . Most said they just didn't understand it. They knew they could place const at different points within a declaration, and they just didn't understand the consequences of the different placement options. For example, the const in:
const char *p;
modifies the char to its immediate right (it declares p as a pointer to a const char ). Does that mean that the const in:
char const* p;
modifies the pointer operator to its immediate right (it declares p as a const pointer to a char )? (Answer: No.)
In the mid-1990s, it occurred to me that it might be easier for programmers to understand const if they learned to apply this fairly simple rule: when writing a declaration, place const to the immediate right of the part of the type that you want to be const ; when reading that declaration, read const just before you read the thing to its immediate left. For example, to declare p as a pointer to const char, write:
char const *p;
To read it aloud, just read it from right to left, as “p is a pointer to a const char .” To declare p as a const pointer to char , write:
char *const p;
To read it aloud, again just read it from right to left.
I've written earlier columns on why this style makes it easier to read and write declarations using const. 1, 2, 3 You can find them at www.dansaks.com.
In the years that I've been using and teaching this style for placing const in declarations, I received a lot of positive feedback that using this style does indeed help. Unfortunately, the converts represent what appears to be a distinct minority of C and C++ programmers. Most C and C++ programmers simply won't do it. Moreover, they won't even try it.
When I ask programmers why they won't try it, they often tell me, “It's not conventional” or, “Hardly anybody does it that way,” to which I offer the following response.
For the last six to eight years, I've been posing the following query to my lecture audiences. Given these declarations in the conventional style:
typedef char *ntcs;const ntcs s;
what is it about s that's const ? Is it (a) the character, or (b) the pointer, or (c) both? (The answer appears at the end of this article.) I've posed this question to thousands (the low single-digit thousands) of programmers and only about 40% get it right.4 The rest either get it wrong or are unable or unwilling to hazard a guess. At the same time, well over 90% of these programmers reported using the conventional style for placing const .
So, when someone tells me they won't use it because it's not conventional, my response is that, in this case, conventional isn't working. Maybe it's time to try something else.
Other times, when I ask programmers why they won't try it, they tell me something like, “It won't work. It'll confuse people.” When I ask, “Have you tried it, or do you know someone who's tried it and been confused by it?” the answer is invariably, “No.” When I ask, “How do you know it won't work if you won't try it?” too often the answer is something like, “It's obvious that it won't.” Not to me it isn't.
Of course, there are those programmers who use the conventional style and understand declarations well enough to correctly interpret:
const ntcs s;
as well as more complex declarations. I can understand why they see no need to adopt a different style. Nonetheless, some programmers who don't need to switch styles for themselves have done it to help coworkers who've struggled with const , and reported positive results.
The keyword const is a very useful feature of C and C++, especially for writing embedded systems. The keyword volatile is also useful and follows rules that are nearly identical to the rules for const . Using const and volatile appropriately is a good thing, and programmers ought to be encouraged to do it. Unfortunately, the conventional style for placing const in declarations doesn't seem to help much.
More than a decade ago, I started using and recommending the alternative style for placing const in declarations. Yes, I know this style takes a little getting used to. Nonetheless, I've had many programmers try it and tell me it helped them use const more effectively.
A lot of people have told me that they don't have to try the alternative style because they know it won't work. Others have speculated on why it might not work as advertised, but have not actually tried it. Still others have told me they wanted to try it, but ran into too much resistance from obstinate colleagues.
I'd like to know if someone out there has actually given this style a serious try and found that it actually makes it harder to program using const . If you could write to me about your experience, I'd appreciate hearing from you.
By the way, the answer is (b). The declaration:
const ntcs s;
declares s as a const pointer to char . If you got it wrong, check out the articles listed below available at www.dansaks.com.
1. Saks, Dan, “Mixing const with Type Names”, The C/C++ Users Journal , December, 1996.
2. Saks, Dan, “Placing const in Declarations”, Embedded Systems Programming , June 1998, p. 19.
3. Saks, Dan, “const T vs. T const”, Embedded Systems Programming , February 1999, p. 13.
4. In my surveys in the past year, closer to 50% have gotten the answer correct. This is better than 40%, but still not good. It's too early to know if this represents a trend.