Please Explain the following code
#include <iostream>
using namespace std;
int main()
{
const int x = 10;
int * ptr;
ptr = (int *)( &x ); //make the pointer to constant int*
*ptr = 8; //change the value of the constant using the pointer.
//here is the real surprising part
cout<<"x: "<<x<<endl; //prints 10, means value is not changed
cout<<"*ptr: "<<*ptr<<endl; //prints 8, means value is changed
cout<<"ptr: "<<(int)ptr<<endl; //prints some address lets say 0xfadc02
cout<<"&x: "<<(int)&x<<endl; //prints the same address, i.e. 0xfadc02
//This means that x resides at the same location ptr points to yet
//two different values are printed, I cant understand this.
return 0;
}
*ptr = 8;
This line causes undefined behavior because you are modifying the value of a const qualified object. Once you have undefined behavior anything can happen and it is not possible to reason about the behaviour of the program.
Since x is a const int, the compiler will most likely, in the places where you use x, directly substitute the value that you've initialized with (where possible). So the line in your source code:
cout<<"x: "<<x<<endl;
will be replaced by this at compile time:
cout<<"x: "<<10<<endl;
That's why you still see 10 printed.
But as Charles explained, the behaviour is undefined, so anything could happen with code like this.
Related
i am learning c++ and i find this bit confusing about the pointers . is it allowed or is it possible to modify the variable int a using pointer variable ?
here's the code :
#include <iostream>
int main(){
int a ; // int variable
int *p ; // pointer
a = 10 ;
*p =15 ;
std:: cout << a ;
return 0;
};
does *p = 15 change the value of a ?
i got error when i tried to run the code :
zsh: bus error
There's no relationship between p and a. p points to invalid memory, and dereferencing or assigning to it is undefined behavior.
If you want modifications to p to affect a, you need to set where it points to.
int a;
int *p = &a;
Silvio's answer is correct.
Bus errors occur when your processor cannot even attempt the memory access requested.
This usually happens when using a processor instruction with an address that does not satisfy its alignment requirements.
you can read more about this here.
You need to assign the address of variable a to the pointer p.
p = &a;
Now, if you will change the value of the pointer to 15 it will be reflected in the variable a. And you won't get an error.
Is int &y=x same as int y=&x?
Are s++ and *s++ the same?
Also in the below code, why is *s++ giving me some wrong results?
I was expecting *s value to be 12
#include <iostream>
using namespace std;
int main()
{
int p=10;
int &q=p; //q is a reference variable to p
//int r=&p; //error: invalid conversion from 'int*' to 'int'
int *s=&p; //valid
q++;
*s++; //here even s++ works, and cout<<*s does not give 12 but some lengthy number
//and cout<<s gives some hexadecimal, I'm guessing thats the address
cout<<p<<endl<<q<<endl<<*s;
}
Output I'm getting:
11
11
6422280
int &y=x same as int y=&x.
In first y is an integer reference which is initialized to x . OTOH, in second you are trying to assign int a value of int * which results in a compilation error .
why is *s++ giving me some wrong results? I was expecting *s value to be 12
This is because ++ has precedence over * , therefore ,first s is incremented first (thus pointing to uninitialized memory location), and then dereferenced .
Which is leading to dereference of uninitialized memory location resulting in undefined behaviour.
If you want to expected value , you can do this -
(*s)++; //dereference first and then increment
Is int &y=x same as int y=&x?
No. They are very different.
int x;
int& y = x; // y is a reference to x.
On the other hand,
int x;
int y = &x; // Should be compiler error.
// Initializing y with a pointer.
The line:
*s++;
is equivalent to:
int* temp = s;
s++;
*temp;
You are evaluating *temp but the side effect is that you are incrementing s. After that s points to the next element. That is not a valid address though. The next time you access *s, the program exhibits undefined behavior. The output of the line:
cout<<p<<endl<<q<<endl<<*s;
can be anything.
Is int &y=x same as int int y=&x?
Not nearly. The first binds the x to the int-reference y, the second initializes the int y with the address of x.
Both can be made to compile cleanly, but the second only with severe contortions abusing operator overloading:
{
int y;
int& x = y;
}
{
// Only for demonstration, never do something this crazy for real
struct { int operator&() { return 0; }; } x;
int y = &x;
}
Are s++ and *s++ the same?
Certainly not, though they have the same effect in your example, as you discard the result:
The first increments s and returns its pre-increment value.
The second does the same, but then dereferences that.
In both cases, s thereafter points behind an object, and may not be dereferenced on pain of Undefined Behavior (UB).
Which explains the curious number you got, but might also have resulted in your program just printing 42 and then beginning to reformat your harddrive (legal but unlikely).
I was surprised that c++ allows incrementing dereferenced pointer to a constant data, which it should not allow through a pointer to a const data. Consider the code:
#include<iostream>
#include<climits>
using namespace std;
int main(){
int x = 2;
const int *xPtr2 = &x;
*xPtr2++;
cout << x << endl;
}
But still the value of x is 2. That means *xPtr2 was not actually incremented. I also tried *xPtr2 = 3, but this time it shows compilation error. Why is it so?
Here the precedence of ++ is more than that of *. Hence
*xPtr2++
is equivalent to
*(xPtr2++)
Since xPtr2 is not a constant pointer but a pointer to constant data, incrementing xPtr2 and dereferencing it is fine in this case (but not others) and hence no compilation error is caused.
The ++ operator has precedence over dereferencing. Basically you're dereferencing the pointer that has been incremented.
For the behavior you're trying to accomplish, you should wrap the pointer in parens.
(*xPtr2)++;
Same goes for assigning - you're trying to assign an int to a int *. It would work with parens.
(*xPtr2) = 3;
See your example in ideone.
You have mentioned
dereferencing pointer to constant data
So, lets consider the following code
#include <stdio.h>
int main() {
const int foo = 0xdead;
int* bar = (int*) &foo;
*bar = 0xcafe;
printf("const int foo = %#x", foo);
return 0;
}
Output : const int foo = 0xcafe
In C, C++ const is just a compile time modifier for variables. This means that the compiler wants no modification to a const at compile time. At runtime there is no concept of const => all local variables are stored in stack, all static and global variables are stored in .data section. Thus you can dereference a const and modify it only at runtime
When I tried below code I got strange results.I am trying to change value of constant by using the pointers.But when I output the results pointer value and the original variable variable value its giving two different values.Can anyone explain what exactly happens when explicit conversion take place?
int main()
{
int *p ;
const int a = 20;
p=(int *)&a;
*p = *p +10;
cout<<"p is"<<*p<<"\na is"<<a;
}
output:
p is 30
a is 20
Both C and C++ say that any attempt to modify an object declared with the const qualifier results in undefined behavior.
So as a is object is const qualified, the *p = *p +10; statement invokes undefined behavior.
First of - You really shouldn't be doing this. const is a constant, meaning don't change it! :)
Now to explain what happens (I think):
The space on the stack is allocated for both variables, p and a. This is done for a because it has been referenced by an address. If you removed p, you'd effectively remove a as well.
The number 20 is indeed written to the a variable, and modified to 30 via p, which is what is being printed.
The 20 printed is calculated at compile time. Since it is a const, the compiler optimized it away and replaced with 20, as if you did a #define a 20.
Don't Do That.
If you would write this code in C++ with an explicit cast, you would get something like this:
int main()
{
int *p ;
const int a = 20;
p= const_cast<int*>(&a); // the change
*p = *p +10;
cout<<"p is"<<*p<<"\na is"<<a;
}
Now, this code tells a bit more about what's going on: the constant is cast to a non-constant.
If you are writing a compiler, constants are special variables that are allowed to be 'folded' in the const folding phase. Basically this means that the compiler is allowed to change your code into this:
int main()
{
int *p ;
const int a = 20;
p= const_cast<int*>(&a);
*p = *p +10;
cout<<"p is"<<*p<<"\na is" << 20; // const fold
}
Because you're also using &a, you tell the compiler to put the value 20 in a memory location. Combined with the above, you get the exact results you describe.
This is undefined behavior.
A compiler can assume that nothing is going to change the value of a const object. The compiler knows that the value of "a" is 20. You told the compiler that. So, the compiler actually goes ahead and simply compiles the equivalent of
cout << "p is" << *p << "\na is" << 20;
Your compiler should've also given you a big fat warning, about "casting away const-ness", or something along the same lines, when it tried to compile your code.
Although it is defined as undefined behaviour (as everyone else tells you), it could be that your compiler has allocated a storage location (int) for the const int; that is why the *p= *p + 10 works, but may have repaced a in the output statement with the value 20, as it is supposed to be constant.
While I was learning about const variables in c++, I tried this :
#include <iostream>
int main()
{
const int p = 20;
int* a = const_cast<int*>(&p);
*a = 10;
std::cout<<"Value at a: "<<(*a)<<std::endl;
std::cout<<"Value of p: "<<p<<std::endl;
std::cout<<"Their addresses : "<<std::endl;
std::cout<<a<<" "<<&p<<std::endl;
return 0;
}
and it produces the output:
Value at a: 10
Value of p: 20
Their addresses :
0x7fff4646d7d4 0x7fff4646d7d4
Seemingly I assigned the value 10 to the memory address of p, but their values come out different. Why is it so?
Attempting to modify an object that was originally declared const gives you undefined behaviour.
ยง7.1.6.1/4 [dcl.type.cv] Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.
Chances are, your compiler is replacing all occurences of p in your code with the value 20, since you have promised that it will not change. So the line that prints p has changed to:
std::cout<<"Value of p: "<<20<<std::endl;
So it prints 20 regardless of whether you modified the original object. Of course, since you have undefined behaviour, this kind of reasoning is fruitless and you should not invoke undefined behaviour in your program.