Variables Won't Constants Aren't:

A random walk through constant values in C++

Secure remote control for conventional and virtual desktops

I first read the lament to the capricity of programming in the title of this piece in Creative Computing, years before C was devised. But it’s still true that there is no way, not even one, of being absolutely sure that a value you set in C or C++ won’t change.

This is despite the fact that in the 30 years following the creation of C, C and C++ have acquired new keywords, features and libraries and have been generally enhanced to a point where my ancient battered copy of Kernighan and Richie hides in a cupboard and refuses to even sit on the desk where Visual C++ 2005 lives.

C++ gives the programmer a menu of methods to help him/her protect his/her data. At least, that’s what’s implied if you don’t read Stroustrup too closely. It’s not that you’re being lied to; it’s just that someone is being rather economical with the truth.

It’s tempting to think that, given:

const int MyConst = 42;
double MyVals[MyConst];
for (int i=0; i != MyConst; i++) {
    // ...

you won’t ever go off the end of the array. Tempting, but wrong; and it is quite trivial to make it happen:

int& x = (int&) MyConst;
x = 43;

The default in C++ is variables, not constants; and thus you probably won’t even get a warning if you do such a thing. And so you implicitly, but silently, cast away constness.

This is one of the many reasons that classical C style casts are frowned upon in most coding standards. But for most programmers these days, the only time that they ever review someone else’s code is at interview [and not always then – Ed] - so probably no-one will notice if they aren’t following standards.

The accepted, but still rather worrying, technique is:

int& CPlusCast = const_cast<int&>(MyConst);

[Am I the only one who thinks this cast has the wrong name? – Dominic]

OK, but when you’re hunting a bug, then you might well be tempted to think that this means that MyConst can’t change. Yet it might or might not mean that; and of course now that constness is gone, MyConst can be passed into a function with a variable parameter signature.

Even specifying:

void Increment(const int& x)

doesn’t mean it won’t ever change - as we’ve seen. More than that, since threads are coming back into mainstream programming, your MyConst value may change randomly at some random point during execution.

You can always try to specify that a function mustn’t change any class variables, which would be really handy if your class is supposed to be inherited from, but again, this can be changed later.

Const functions only protect members of the class, and the language also stops you getting around this by getting the const function to call a non-const member. But the syntactic protection does not extend to globals; although if you use them you’re not really into this level of discipline anyway.

And it just wouldn’t be C++ if there weren’t yet another workaround available. So, we can specify member variables as mutable, and thus make them prey to random change by the sort of people who think “const member function” actually means that only externally observable states should remain constant; and that the function should be free to meddle with its private housekeeping variables.

But sometimes you need to expose some internal structure like the STL string or MFC CString, so that you can use the character buffer with older code. STL does the right, but fallible, thing and so the c_str() member returns a const pointer; which at least takes some effort if you’re determined to corrupt it. MFC doesn’t even try.

STL also has const_iterators, which of course aren’t constant (because there wouldn’t be much point having an index that didn’t change); but the idiom is that you can’t directly change the values of the collection, which is both safer and potentially rather faster. An iterator that you know won’t change things can not only be cached, but is also rather easier to multithread.

Now, so far I’ve only complained about intentional changes to variables. We also have to live with the possibility of memory being trashed, since const is just a syntactic sugar coating for the bitter reality of the underlying memory model. Hence, in Visual C++ 2005, I can illustrate a simplified example of a const value being trampled on simply for being too close to another on the stack:

void HeisenBug(void) {
    char a = 42;
    char Bug[5];
    strcpy(Bug, "123456789abcdefghijk");

Note that this mucks up the value “before” the Bug array; and that this is compiler-dependent. This effect may be anything from benign to subtly malicious.

Of course, if you’re in the IDE of a decent debugger like Visual Studio 2005, then this effect will be caught; but if you’re in production code, you simply get a silent change of the value. The debug code will contain traps for this, but these disappear in release; and of course optimised code is the most vulnerable. Live fast die young. And so we get a “Heisenbug”, an error that changes when you try to observe it in the debugger. This could still happen if the “constant” string was #defined, because the value has to be somewhere, even if the compiler has folded long strings.

Now, modern operating systems allow you to write-protect blocks of memory; but that is both non-portable and deeply ugly - and you’ve probably worked out for yourself that it can be turned off by the same API. In older compilers, it is also entirely possible for explicit constants to be changed; and Microsoft actually used to advise developers to write code such as:

char* Fname = " ImpliedVol"; // Note the space at the start of the name
Fname[0] = (BYTE) strlen(Fname);

to cope with BASIC-style APIs that required the length of the string to be in the first byte. It worked - yes, really; a large percentage of the world’s derivative pricing makes its way into dealing systems that way - but Microsoft now makes all literal strings read only, which is more elegant. Although it does mean that, a whole pile of its example code now won’t work anymore.

And, of course, any memory value can be hit by a stray pointer.

However, it’s not all bad as const can also be a big hint to the compiler to make better code. If you have a big vector of some class, then default pass by value means that a simple utility algorithm like:

template <typename T> double Sum(vector<T> vec)

may end up calling the constructor many times. As it happens, STL is smart enough to keep this to a minimum; but if we write:

template <typename T> double Sum(const vector<T>& vec)

then we are telling the compiler quite explicitly that vec is basically just an alias to the variable in the calling function; and then it’s much easier for the compiler to generate direct inline access. Thus, const references can make your code both faster and more robust.

So, to summarise, C++ does do constants, and often they are useful, but they are never completely trustworthy. ®

Top 5 reasons to deploy VMware with Tegile

More from The Register

next story
New 'Cosmos' browser surfs the net by TXT alone
No data plan? No WiFi? No worries ... except sluggish download speed
iOS 8 release: WebGL now runs everywhere. Hurrah for 3D graphics!
HTML 5's pretty neat ... when your browser supports it
Mathematica hits the Web
Wolfram embraces the cloud, promies private cloud cut of its number-cruncher
Mozilla shutters Labs, tells nobody it's been dead for five months
Staffer's blog reveals all as projects languish on GitHub
'People have forgotten just how late the first iPhone arrived ...'
Plus: 'Google's IDEALISM is an injudicious justification for inappropriate biz practices'
SUSE Linux owner Attachmate gobbled by Micro Focus for $2.3bn
Merger will lead to mainframe and COBOL powerhouse
iOS 8 Healthkit gets a bug SO Apple KILLS it. That's real healthcare!
Not fit for purpose on day of launch, says Cupertino
Netscape plugins about to stop working in Chrome for Mac
Google kills off 32-bit Chrome, only on Mac
prev story


Secure remote control for conventional and virtual desktops
Balancing user privacy and privileged access, in accordance with compliance frameworks and legislation. Evaluating any potential remote control choice.
Intelligent flash storage arrays
Tegile Intelligent Storage Arrays with IntelliFlash helps IT boost storage utilization and effciency while delivering unmatched storage savings and performance.
WIN a very cool portable ZX Spectrum
Win a one-off portable Spectrum built by legendary hardware hacker Ben Heck
High Performance for All
While HPC is not new, it has traditionally been seen as a specialist area – is it now geared up to meet more mainstream requirements?
Beginner's guide to SSL certificates
De-mystify the technology involved and give you the information you need to make the best decision when considering your online security options.