Can someone explain to me as why this code works? I feel like the compiler should not allow me to do what I have done (move an int pointer to point at a const int), or alternatively I would at least expect a compiler warning or a segfault. The idea of changing the value of a constant just seems so wrong.
Code:
#include <iostream>
using namespace std;
struct test_struct {
int i;
const int j;
};
int main() {
cout << "Create a struct with int i = 100 and const int j = 101." << endl;
test_struct test{100, 101};
cout << test.i << endl;
cout << test.j << endl;
cout << "Create pointer p and point it to int i." << endl;
int* p1 = &test.i;
cout << *p1 << endl;
cout << "Increment pointer p, which should now be pointing at const int j." << endl;
p1++;
cout << *p1 << endl;
cout << "Dereference p and increment it." << endl;
(*p1)++;
cout << *p1 << endl;
cout << test.j << endl;
}
Output:
Create a struct with int i = 100 and const int j = 101.
100
101
Create pointer p and point it to int i.
100
Increment pointer p, which should now be pointing at const int j.
101
Dereference p and increment it.
102
102
In C or C++, we can use the constant variables. The constant variable values cannot be changed after its initialization. In this section we will see how to change the value of some constant variables. If we want to change the value of constant variable, it will generate compile time error.
The increment operator obviously cannot applied for a const (ant) variable, because the const keyword prevents it to be changed after the initial definition. That's why the compiler error is issued.
C programming has two operators increment ++ and decrement -- to change the value of an operand (constant or variable) by 1. Increment ++ increases the value by 1 whereas decrement -- decreases the value by 1.
A constant is a literal value that can be called from any expression, so it can be reused across multiple objects throughout the system. Each time you modify and save a constant, a new version is created. All expressions that use the constant use the latest version.
You program invokes undefined behavior in two ways, which means the behavior of your program is unpredictable, even seemingly normal behavior is possible.
First although we can treat the individual elements of a struct as arrays once you increment the pointer it is no longer valid to dereference it, it does not not even have to be pointing to the next element it could very well be pointing to padding.
Second, attempting to alter a const in also undefined behavior. The draft C++ standard section 7.1.6.1
The cv-qualifiers paragraph 4 which says:
[...]any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.
We can see for the purposes of pointer arithmetic a non-array variable is treated as an array of one element, from section 5.7
Additive operators which says:
For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
and furthermore dereferecing one past the end of an array is undefined behavior, from the same section:
When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. [...] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
we can further see from section 5.3.1
Unary operators which says:
The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function
when we dereference a pointer we expect and object which we are not guaranteed to have once we are one past the end.
The The GNU C++ Library has an easier to access explanation which says (emphasis mine):
You can only dereference a pointer that points into an array. If your array pointer points outside the array -- even to just one past the end -- and you dereference it, Bad Things happen.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With