November 13, 2005
How const is const?
Here is some straightforward C++ code:
int a[5];
The variable "a" is declared as being an array of 5 integers. This code is equivalent:
const int n = 5;
int a[n];
The variable "n" is a compile-time constant and can be used interchangeably with the constant 5. The address of a global variable is also a compile-time constant. Therefore, this is valid C++ as well:
int b;
const int n = reinterpret_cast<int>(&b);
And it does indeed compile, at least under Visual C++ 2005. The variable "n" no longer has the value 5. It has the value of the address of "b" reinterpreted as an integer.
Now the interesting part (to me anyway!). What if I combine the two examples so that the constant "n" is initialized with the address of "b" and then "n" is used as the size of the array "a"?
int b;
const int n = reinterpret_cast<int>(&b);
int a[n];
Although "n" has the same datatype as it did previously (constant integer), this code results in a compile time error under Visual C++. I can understand why this is the case. Consider:
// foo.cpp
extern int b = 0;
// bar.cpp
extern int b;
const int n = reinterpret_cast<int>(&b);
int a[n];
The compiler has no way of knowing the value of "n" at compile time. Only the linker has sufficient information to determine its value. But this is too late because the compiler is responsible for allocating the storage for the array "a".
My conclusion is that the type of "n" seems to go beyond its declared type of constant integer. Behind the scenes, the compiler must track whether "n" can be resolved at compile time or not. Sort of like, is "n" constant or really constant.
The morale of the story? Never fool yourself into thinking you fully understand C++!
int a[5];
The variable "a" is declared as being an array of 5 integers. This code is equivalent:
const int n = 5;
int a[n];
The variable "n" is a compile-time constant and can be used interchangeably with the constant 5. The address of a global variable is also a compile-time constant. Therefore, this is valid C++ as well:
int b;
const int n = reinterpret_cast<int>(&b);
And it does indeed compile, at least under Visual C++ 2005. The variable "n" no longer has the value 5. It has the value of the address of "b" reinterpreted as an integer.
Now the interesting part (to me anyway!). What if I combine the two examples so that the constant "n" is initialized with the address of "b" and then "n" is used as the size of the array "a"?
int b;
const int n = reinterpret_cast<int>(&b);
int a[n];
Although "n" has the same datatype as it did previously (constant integer), this code results in a compile time error under Visual C++. I can understand why this is the case. Consider:
// foo.cpp
extern int b = 0;
// bar.cpp
extern int b;
const int n = reinterpret_cast<int>(&b);
int a[n];
The compiler has no way of knowing the value of "n" at compile time. Only the linker has sufficient information to determine its value. But this is too late because the compiler is responsible for allocating the storage for the array "a".
My conclusion is that the type of "n" seems to go beyond its declared type of constant integer. Behind the scenes, the compiler must track whether "n" can be resolved at compile time or not. Sort of like, is "n" constant or really constant.
The morale of the story? Never fool yourself into thinking you fully understand C++!