Constant Joy (4)

Constant Joy (4)

The const keyword in C is a useful tool with different meanings in different contexts. In my first three articles, I explained these different meanings and illustrated their application. This is more an opinion piece on the value of const and different approaches.

In the late nineties, Microsoft released a new version of their C compiler. My team evaluated the new version and decided to adopt it, but we had a problem. The old compiler simply did not enforce const-checking with read-only pointer, that is, a pointer to a const value. The new compiler remedies this, and revealed hundreds of misuses of const in our substantial code-base. As the most junior member of the team, I was given the task of repairing all these misuses. The cost of allocating me to this task, which would not yield any commercial benefit, was keenly felt, as it emerged that the task would take days, if not weeks. My work was scrutinized, to see why I was taking so long, and the size of the task was fully understood. We had const objects that were illegally referenced with read-write pointers and we had mixed up read-only pointers with read-write pointers. Untangling this was a lot of work.

One of the most senior team members expressed the view that using const was a waste of time. He said it was pointless because, sooner or later, you would have to use third-party code where they had not used any read-only pointers and you would have to use unsafe casts to get your code to compile. At the time, what he was saying seemd to make sense. At the same time, I felt that this approach was a bit defeatist, and that it should be possible to use const correctly and consistently within your own code, and to isolate casts relating to third-party code in a thin-layer interface. And I could see that getting the compiler to check const could and did save debugging and maintenance costs down the line, even if it felt like it slowed down development at first.

One of the key principles of functional programming is that all variables are immutable. The idea springs from a wealth of evidence that some programming errors relate to mutable variables, and that mutable variables are unnecessary (when you replace loops with recursion). There are a few reasons why you might not want to use every aspect of the pure functional programming style when constructing a resource-constrained, embedded C project. But decorating unchanging variables with const has a very small cost and a substantial benefit.

So I like to use const as widely as is possible. I will delay the introduction of a local variable until I have its initial value, so that I can make it const. Every read-only pointer is declared with const, so that the compiler can enforce the read-only property. And I recognize that some people take a completely different stance. I claim that my large-scale, mature software projects are more cost-effective to maintain through using const, but I have no proof. If you find yourself in a development community that does not like to use const, you can gently introduce the merits of const, but respect that there are lots of ways to construct reliable, high-quality software.