First, sorry for possible question redundancy.
Doing some little experiments with C/C++ pointers in GCC I encountered this somewhat weird behaviour when bypassing constantness of value at the pointer address.
#include <iostream>
int main()
{
using namespace std;
const double number = 100;
//bypassing constantess of pointed-to value
double * pointer_to_value = (double *) &number;
*pointer_to_value += 200;
cout << "Adress of number: " << &number << "\tValue of number: " << number << endl <<
" Pointer value: " << pointer_to_value << "\tDereferencing pointer: " << *pointer_to_value;
return 0;
}
I would expect both form of checking the value yielding same results. Location of value is same in both cases. Program generates following output, however:
Adress of number: 0x22ff30 Value of number: 100
Pointer value: 0x22ff30 Dereferencing pointer: 300
Anyone capable of explaining?
Thanks in advance.
It's undefined behaivor.
It's irrelevant why exactly it happens (actually because the compiler inlines the value).
"UnConsting” const value via pointer is a Undefined Behavior.
So it is not posible to define a behavior not defined by the Standard.
Compiler optimization. Compiler doesn't expect you to try and trick it like that, it knows that the value is const, so it just cached it. Try to compile it without any optimization, and see if it makes any difference.
Generally the meaning of const is:
constant - the object shall not be modified. Attempt to do so results in undefined behavior. On most of the compilers it is compile-time error.
Compiler optimization. You can overcome that by adding volatile keyword to the variable.
#include <iostream>
int main()
{
using namespace std;
volatile const double number = 100;
//bypassing constantess of pointed-to value
double * pointer_to_value = (double *) &number;
*pointer_to_value += 200;
cout << "Adress of number: " << &number << "\tValue of number: " << number << endl <<
" Pointer value: " << pointer_to_value << "\tDereferencing pointer: " << *pointer_to_value;
return 0;
}
My guess is that gcc has done some optimizations on your behalf, replacing the reference to << number with << 100. Should be possible to verify by looking at the generated asm code.
Related
When I tried to access the value(which is an address) stored in the address pointed by the pointer variable, a garbage value is returned. I have posted the code and the output below.
Code:
#include<iostream>
using namespace std;
int main(){
int *a, b=10, *c;
a = &b;
c = &b+1;
cout << "Address of A : " << &a << endl;
cout << "Value of A : " << a << endl;
cout << "Value pointed by A : " << *a << endl;
cout << "Address of B : " << &b << endl;
cout << "Value of B : " << b << endl;
cout << "Value of C : " << c << endl;
cout << "Value pointed by C : " << *c << endl;
return 0;
}
Output:
Address of A : 0x7fff3e608d20
Value of A : 0x7fff3e608d1c
Value pointed by A : 10
Address of B : 0x7fff3e608d1c
Value of B : 10
Value of C : 0x7fff3e608d20
Value pointed by C : 1046514972
In the above program, the address pointed by c is the address of a yet *c gives garbage value 1046514972 instead of 0x7fff3e608d1c.
I know, I can access the value of A in some other way but my question is why couldn't I access it in this way. Is this an expected behaviour? If yes, can somebody please explain? Thank you.
c = &b+1;
//...
*c
That's undefined behaviour. Forming a pointer to the location after a variable is valid, but performing indirection through it is not1. Even though some object happens to be there, the compiler is free to do whatever it wants.
As to why 1046514972 is printed, that's 0x3e608d1c in hex. It's just the bytes of the 64 bit pointer reinterpreted as a 32 bit integer. You just happen to get something which kind of makes sense, but since this is undefined behaviour, it's semantically garbage.
1 Technically it's the l-to-rvalue conversion which is undefined, but you don't have to worry about that.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 years ago.
I have this code:
#include <iostream>
using namespace std;
int & squareRef(int );
int main() {
int number1 = 8;
cout << "In main() &number1: " << &number1 << endl;
int & result = squareRef(number1);
// cout << "In main() &result: " << &result << endl;
cout << result << endl;
cout << result << endl;
cout << number1 << endl;
}
int & squareRef(int rNumber) {
cout << "In squareRef(): " << &rNumber << endl;
rNumber *= rNumber;
return rNumber;
}
The program produces the following output:
In main() &number1: 0x28ff08
In squareRef(): 0x28fef0
64
1875681984
8
Can anyone please explain why the two "results" are different , is that suppose to be same isn't ?
You are invoking undefined behaviour by returning a reference to a local variable:
test.cc:19:7: error: reference to local variable ‘rNumber’ returned [-Werror=return-local-addr]
int & squareRef(int rNumber) {
rNumber is copied on the stack for the call. After the call, the value on the stack is undefined, and might well change due to subsequent calls. The reference you return only points to that location on the stack and does not hold the actual value.
In general, when these things happen, it is very helpful to turn on all warnings your compiler can give you. With gcc, the flags -Wall -Wextra -Werror provide you with a lot of helpful warnings, such as these. In general, code should compile without throwing any warnings (except maybe unused variables/parameters in function stubs, although there are macros to explicitly skip over these).
Why after using strdup(value) (int)value returns you different output than before?
How to get the same output?
My short example went bad, please use the long one:
Here the full code for tests:
#include <stdio.h>
#include <iostream>
int main()
{
//The First Part
char *c = "ARD-642564";
char *ca = "ARD-642564";
std::cout << c << std::endl;
std::cout << ca << std::endl;
//c and ca are equal
std::cout << (int)c << std::endl;
std::cout << (int)ca << std::endl;
//The Second Part
c = strdup("ARD-642564");
ca = strdup("ARD-642564");
std::cout << c << std::endl;
std::cout << ca << std::endl;
//c and ca are NOT equal Why?
std::cout << (int)c << std::endl;
std::cout << (int)ca << std::endl;
int x;
std::cin >> x;
}
Because an array decays to a pointer in your case, you are printing a pointer (ie, on non-exotic computers, a memory address). There is no guarantee that a pointer fits in an int.
In the first part of your code, c and ca don't have to be equal. Your compiler performs a sort of memory optimization (see here for a full answer).
In the second part, strdup allocates dynamically a string twice, such that the returned pointers are not equal. The compiler does not optimize these calls because he does not seem to control the definition of strdup.
In both cases, c and ca may not be equal.
"The strdup() function shall return a pointer to a new string, which is a duplicate of the string pointed to by s1." source
So it's quite understandable that the pointers differ.
I have read everywhere that a reference has to be initialized then and there and can't be re-initialized again.
To test my understanding, I have written the following small program. It seems as if I have actually succeeded in reassigning a reference. Can someone explain to me what is actually going on in my program?
#include <iostream>
#include <stdio.h>
#include <conio.h>
using namespace std;
int main()
{
int i = 5, j = 9;
int &ri = i;
cout << " ri is : " << ri <<"\n";
i = 10;
cout << " ri is : " << ri << "\n";
ri = j; // >>> Is this not reassigning the reference? <<<
cout << " ri is : " << ri <<"\n";
getch();
return 0;
}
The code compiles fine and the output is as I expect:
ri is : 5
ri is : 10
ri is : 9
ri = j; // >>> Is this not reassigning the reference? <<<
No, ri is still a reference to i - you can prove this by printing &ri and &i and seeing they're the same address.
What you did is modify i through the reference ri. Print i after, and you'll see this.
Also, for comparison, if you create a const int &cri = i; it won't let you assign to that.
It seems as if I have actually succeeded in reassigning a reference.
Is that true?
No, you haven't. You are actually reassigning the value, and you are not rebinding the reference.
In your example, when you do int &ri = i;, ri is bound to i for its lifetime. When you do ri = j;, you are simply assigning the value of j to ri. ri still remains a reference to i! And it results in the same outcome as if you had instead written i = j;
If you understand pointers well, then always think of the reference as an analogical interpretation of T* const where T is any type.
When you assign something to a reference you actually assign the value to the object the reference is bound to. So this:
ri=j;
has the same effect as
i = j;
would have because ri is bound to i. So any action on ri is executed on i.
You cannot "reseat" a reference(https://isocpp.org/wiki/faq/references#reseating-refs).
One useful mantra with references in C++ is that the references are the object they refer to. Any change you make to it is to make change to what ever they refer to. Using the mantra you can probably see what's happening when you do ri = j, i now is j.
You are not reassigning the reference when executing ri = j;. You're actually assigning j to i. Try printing i after the line and you'll see that i changed value.
OP asked for altering the referenced object through assignment to the reference and was very correctly told that this changed the reference object, not the reference.
Now I did a more poignant attempt at really changing the reference and found potentially nasty stuff.
First the code. It attempts to reassign to the reference var a newly created object, then alters the reference aka referenced object, finds that this is not reflected in the apparently referenced objects and concludes that we may have a case of a dangling pointer in C++. Sorry for the hastily composed code.
using namespace std;
vector<int>myints;
auto &i = myints.emplace_back(); // allocate and reference new int in vector
auto myintsaddr = &myints; auto myintfrontaddr = &myints.front(); // for future reference
i = 1; // assign a value to the new int through reference
cout << hex << "address of i: 0x" << &i << " equals " << "address of
myints.back(): 0x" << &myints.back() << '.' << endl; // check reference as expected
i = myints.emplace_back(); // allocate new int in vector and assign to old reference variable
i = 2; // give another value to i
cout << "i=" << i << ", myints={" << myints[0] << ", "<< myints[1] << '}' << endl; // any change to potentially referenced objects?
cout << hex << "&i: 0x" << &i << " unequal to " << "&myints.back(): 0x" << &myints.back() << " as well as &myints.front(): 0x" << &myints.front() << endl;
cout << "Myints " << (myintsaddr== &myints?"not ":"") << "relocated from " << myintsaddr << " to " << &myints << endl;
cout << "Myints front() " << (myintfrontaddr == &myints.front() ? "not " : "") << "relocated from " << myintfrontaddr << " to " << &myints.front() << endl;
Output:
address of i: 0x0063C1A0 equals address of myints.back(): 0x0063C1A0.
i=2, myints={1, 0}
&i: 0x0063C1A0 unequal to &myints.back(): 0x0063F00C as well as &myints.front(): 0x0063F008
Myints not relocated from 0039FE48 to 0039FE48
Myints front() relocated from 0063C1A0 to 0063F008
Conclusion: at least in my case (VS2017) the reference has kept the exact same address in memory, but the referenced values (part of the vector) have been reallocated elsewhere. Reference i may be dangling.
In simple words,
ri = j; <- You are writing value of j in x(ri) memory. And ri will still hold or point to x.
const int a = 1;
int *p = const_cast<int*>(&a);
*p = 2;
cout << “value a=”<< a << endl;
cout << “value *p=” <<*p << endl;
cout << “address a=” <<&a << endl;
cout << “address p=” <<p << endl;
output:
value a=1
value *p=2
address a=0xbff1d48c
address p=0xbff1d48c
WHY???
why same addr ,diff value?
confused.
thank you!
In C++ language it is illegal to attempt to modify constant objects. Such an attempt results in undefined behavior.
In your program the *p = 2 assignment attempts to modify a constant object a. The behavior is undefined. The weird output you observe is exactly that: undefined behavior.
There's no meaningful explanation for undefined behavior.
(Your compiler probably translated the cout << a; statement into cout << 1;, since the value of a cannot legally change. So, regardless of what you do to your a, 1 will always be printed.)
In addition to AndreyT, you might be wondering that if editing a constant gives undefined behavior then why do we need const_cast<> ? The const_cast<> is meant for getting write privilege for the values which are not write protected by birth. Just try below changes and it should give proper behavior:
int b = 1; // 'b' is modifiable
const int a = b;
...