#include <iostream>
int main()
{
const int i=10;
int *p =(int *) &i;
*p = 5;
cout<<&i<<" "<<p<<"\n";
cout<<i<<" "<<*p;
return 0;
}
Output:
0x22ff44 0x22ff44
10 5
Please Explain.
Well, your code obviously contains undefined behaviour, so anything can happen.
In this case, I believe what happens is this:
In C++, const ints are considered to be compile-time constants. In your example, the compiler basically replaces your "i" with number 10.
You've attempted to modify a const object, so the behavior is
undefined. The compiler has the right to suppose that the const
object's value doesn't change, which probably explains the
symptoms you see. The compiler also has the right to put the
const object in read only memory. It generally won't do so for
a variable with auto lifetime, but a lot will if the const has
static lifetime; in that case, the program will crash (on most
systems).
I'll take a shot at it: since there's no logical reason for that output, the compiler must have optimised that wretched cout<<i<<" " to a simple "cout<<"10 ". But it's just a hunch.
Related
How variable int a is in existence without object creation? It is not of static type also.
#include <iostream>
using namespace std;
class Data
{
public:
int a;
void print() { cout << "a is " << a << endl; }
};
int main()
{
Data *cp;
int Data::*ptr = &Data::a;
cp->*ptr = 5;
cp->print();
}
Your code shows some undefined behavior, let's go through it:
Data *cp;
Creates a pointer on the stack, though, does not initialize it. On it's own not a problem, though, it should be initialized at some point. Right now, it can contain 0x0badc0de for all we know.
int Data::*ptr=&Data::a;
Nothing wrong with this, it simply creates a pointer to a member.
cp->*ptr=5;
Very dangerous code, you are now using cp without it being initialized. In the best case, this crashes your program. You are now assigning 5 to the memory pointed to by cp. As this was not initialized, you are writing somewhere in the memory space. This can include in the best case: memory you don't own, memory without write access. In both cases, your program can crash. In the worst case, this actually writes to memory that you do own, resulting in corruption of data.
cp->print();
Less dangerous, still undefined, so will read the memory. If you reach this statement, the memory is most likely allocated to your program and this will print 5.
It becomes worse
This program might actually just work, you might be able to execute it because your compiler has optimized it. It noticed you did a write, followed by a read, after which the memory is ignored. So, it could actually optimize your program to: cout << "a is "<< 5 <<endl;, which is totally defined.
So if this actually, for some unknown reason, would work, you have a bug in your program which in time will corrupt or crash your program.
Please write the following instead:
int main()
{
int stackStorage = 0;
Data *cp = &stackStorage;
int Data::*ptr=&Data::a;
cp->*ptr=5;
cp->print();
}
I'd like to add a bit more on the types used in this example.
int Data::*ptr=&Data::a;
For me, ptr is a pointer to int member of Data. Data::a is not an instance, so the address operator returns the offset of a in Data, typically 0.
cp->*ptr=5;
This dereferences cp, a pointer to Data, and applies the offset stored in ptr, namely 0, i.e., a;
So the two lines
int Data::*ptr=&Data::a;
cp->*ptr=5;
are just an obfuscated way of writing
cp->a = 5;
I am a c++ learner. Others told me "uninitiatied pointer may point to anywhere". How to prove that by code.?I made a little test code but my uninitiatied pointer always point to 0. In which case it does not point to 0? Thanks
#include <iostream>
using namespace std;
int main() {
int* p;
printf("%d\n", p);
char* p1;
printf("%d\n", p1);
return 0;
}
Any uninitialized variable by definition has an indeterminate value until a value is supplied, and even accessing it is undefined. Because this is the grey-area of undefined behaviour, there's no way you can guarantee that an uninitialized pointer will be anything other than 0.
Anything you write to demonstrate this would be dictated by the compiler and system you are running on.
If you really want to, you can try writing a function that fills up a local array with garbage values, and create another function that defines an uninitialized pointer and prints it. Run the second function after the first in your main() and you might see it.
Edit: For you curiosity, I exhibited the behavior with VS2015 on my system with this code:
void f1()
{
// junk
char arr[24];
for (char& c : arr) c = 1;
}
void f2()
{
// uninitialized
int* ptr[4];
std::cout << (std::uintptr_t)ptr[1] << std::endl;
}
int main()
{
f1();
f2();
return 0;
}
Which prints 16843009 (0x01010101). But again, this is all undefined behaviour.
Well, I think it is not worth to prove this question, because a good coding style should be used and this say's: Initialise all variables! One example: If you "free" a pointer, just give them a value like in this example:
char *p=NULL; // yes, this is not needed but do it! later you may change your program an add code beneath this line...
p=(char *)malloc(512);
...
free(p);
p=NULL;
That is a safe and good style. Also if you use free(p) again by accident, it will not crash your program ! In this example - if you don't set NULL to p after doing a free(), your can use the pointer by mistake again and your program would try to address already freed memory - this will crash your program or (more bad) may end in strange results.
So don't waste time on you question about a case where pointers do not point to NULL. Just set values to your variables (pointers) ! :-)
It depends on the compiler. Your code executed on an old MSVC2008 displays in release mode (plain random):
1955116784
1955116784
and in debug mode (after croaking for using unitialized pointer usage):
-858993460
-858993460
because that implementation sets uninitialized pointers to 0xcccccccc in debug mode to detect their usage.
The standard says that using an uninitialized pointer leads to undefined behaviour. That means that from the standard anything can happen. But a particular implementation is free to do whatever it wants:
yours happen to set the pointers to 0 (but you should not rely on it unless it is documented in the implementation documentation)
MSVC in debug mode sets the pointer to 0xcccccccc in debug mode but AFAIK does not document it (*), so we still cannot rely on it
(*) at least I could not find any reference...
Look at this program:
#include <iostream>
using namespace std;
int main()
{
const int x = 0;
int *p;
p=(int*)&x;
(*p)++;
cout<<x<<endl;
cout<<*p;
}
As you see above, I declared x as a const int, and using casting, a non const pointer named p is points to it. In the middle of the body of my program, I increased the value of x by one using (*p)++ (How is it possible, while x is defined as const?)
Now,when I print *p and x, they returns different values, while *p is supposed to point to address of x :
ap1019#sharifvm:~$ ./a.out
0
1
Why?
The change of variable after constant removal causes the undefined behaviour, in some cases it will just work as if it wouldn't be const, in some it will cause the memory violation error, in some, it will turn your computer into the rabbit which will try to kill you...
A bit of background on the behaviour. Imagine you are a compiler. You encounter the variable:
const int blah = 3;
And then you encounter the following operation:
int foo = 4 + blah;
As you are smart compiler and you know that blah is constant - therefore it will not change, instead of reading the value from the blah, you can exchange the value from get the blah storage place in memory read it to simply add the 3 to 4 and assign it to foo.
Infant you will probably assign 7 straight away because doing the addition is pointless each time you run the program.
Lets now get into the casting away the const part.
Some really sneaky programmer is doing the following:
int * blah_pointer = (int *) & blah;
Then he is increasing the blah value by doing this operation:
(*blah_pointer)++;
What will happen - if the variable is not in the protected memory (not read only) the program will just increase the value of variable stored in memory.
Now when you will read the value which is stored in the pointer you will get the increased value!
Ok but why is there an old, unchanged value if you are reading just the blah I hear you ask:
std::cout << blah;
It is there, because the compiler try to be smart and instead of actually reading the value from blah it will just exchange it to a constant value to blah, so instead of reading it it will actually exchange it to std::cout << 3.
The undefined part is changing the constant value - you can't ever know whether the value will be stored in protected or unprotected region therefore you can't tell what will happen.
If you want the compiler to actually check the value each time it encounters it just change the definition from:
const int blah = 3;
to
const volatile int blah = 3;
It will tell the compiler the following, even though the program I am writing is not allowed to change the blah value, it may be changed during the execution of the program, therefore do not try to optimise the access to the memory and read it every time the value is used.
I hope this makes it clearer.
I think, in compilation step, your compiler will replace all your constant variables with its values (it's like #define), it's the way GNU GCC compiler optimize the code.
I'm not 100% sure about it, but i've got the same issue while learning C/C++ syntax, and it's the conclusion that i've made after disassebling (converting the binary executable to assembler code) my program.
Anyways, just try to disassemble your output and see what is really happening.
I've been coding for a while in other languages and am pretty proficient, but now I am diving more deeply into C++ and have come across some weird problems that I never had in other languages. The most frustrating one, which a google search hasn't been able to answer, is with two different code orders.
The background is that I have an array of integers, and a pointer an element in the array. When I go to print the pointer one method prints correctly, and the other prints nonsense.
An example of the first code order is:
#include <iostream>
using namespace std;
void main(){
int *pAry;
int Ary[5]={2,5,2,6,8};
pAry=&Ary[3];
cout<<*pAry<<endl;
system("pause");
}
and it works as expected. However this simple order wont work for the full project as I want other modules to access pAry, so I thought a global define should work, since it works in other languages. Here is the example:
#include <iostream>
using namespace std;
int *pAry;
void evaluate();
void main(){
evaluate();
cout<<*pAry<<endl;
system("pause");
}
void evaluate(){
int Ary[5]={2,5,2,6,8};
pAry=&Ary[3];
}
When I use this second method the output is nonsense. Specifically 1241908....when the answer should be 6.
First I would like to know why my global method isn't working, and secondly I would like to know how to make it work. Thanks
In the second example, Ary is local to the function evaluate. When evaluate returns, Ary goes out of scope, and accessing it's memory region results in undefined behaviour.
To avoid this, declare Ary in a scope where it will still be valid at the time you try to access it.
It's not working because your pAry is pointing into a local array, which is destroyed when you return from evaluate(). That's undefined behavior.
One possible fix is to make your local array static:
static int Ary[5]={2,5,2,6,8};
In the evaluate() function, you're aiming pAry at a variable (actually array element) local to that function. A pointer can only be dereferenced as long as the object to which it points still exists. Local objects cease to exist when they go out of scope; in this case, this means all elements of Ary cease to exist when evalute() ends, and thus pAry becomes a dangling pointer (it doesn't point anywhere valid).
Dereferncing a dangling pointer gives undefined behaviour; in your particular case, it outputs a garbage value, but it might just as well crash or (worst of all) appear to work fine until the program changes later.
To solve this issue, you can either make Ary global as well, or make it static:
void evaluate(){
static int Ary[5]={2,5,2,6,8};
pAry=&Ary[3];
}
A static local variable persists across function calls (it exists from first initialisation until program termination), so the pointer will remaing valid.
The problem is that you need to declare Ary with file scope.
int Ary[] = {1,2,3,4,5};
void print_ary(void); // The void parameter is a style thingy. :-)
int main(void)
{
print_ary();
return EXIT_SUCCESS;
}
void print_ary(void)
{
for (unsigned int i = 0; i < (sizeof(Ary) / sizeof(Ary[0]); ++i)
{
std::cout << Ary[i] << std::endl;
}
}
A better solution would be to pass a std::vector around to your functions rather than using a global variable.
Check this example for const_cast of int.
I am using VC++ 2008 to compile this.
#include <iostream>
using namespace std;
void main() {
const int x=0;
int y=90;
int *p = const_cast<int *> (&x);
*p=y;
cout<<" value of x: "<<x<<" addr of x "<<&x<<endl
<<" and *p : "<<*p<<" and addr p "<<p<<endl;
}
================
The output is
value of x: 0 addr of x 0012FF60
and *p : 90 and addr p 0012FF60
You should not const_cast a variable defined as const. I don't have the standard at hand but I'm fairly certain it defines such an operation as resulting in undefined behaviour.
For an example of why this results in undefined behaviour consider an MCU where things defined as const are stored in non-volatile memory (flash, EEPROM or something even less volatile).
There's more to read in the C++ FAQ Lite.
For the following program
#include <iostream>
int main() {
const int x=0;
int y=90;
int *p = const_cast<int *> (&x);
*p=y;
std::cout << " value of x: " << x << " addr of x " << &x << '\n'
<< " and *p : " << *p << " and addr p " << p << '\n';
return 0;
}
VC9 prints the same address for me. However:
You are invoking undefined behavior, because you are not allowed to cast away const from an object if that object was a real const value. (OTOH, you are, for example, allowed to cast away const from a const reference if that reference refers to a non-const value.)
In theory, when you invoke undefined behavior, according to the C++ standard your program might work as you expect, or it might not, or it might do so only on Sundays, or unless it's a holiday and full moon. But it might just as well format your HD, blow up your monitor, and make your girlfriend pregnant. According to the C++ standard, all this (and an infinite amount of other possibilities), are Ok.
In practice, such a program might print out funny addresses.
The compiler might completely optimize away all your code and just put in dummy values for printing. It shouldn't, however, do so for Debug builds. (Although that's a QoI issue, not a requirement.)
The compiler is optimizing away the aliasing. Try it in debug mode, with optimizations disabled.
edit
The compiler is optimizing away the aliasing, yes, but it's not an error in the optimization. Rather, the code is doing something undefined, which is leading to an unwanted but legal behavior. Staffan's answer clarifies this.
As the FAQ said, in almost all cases where you're tempted to use const_cast, you should be using mutable instead. If, as in the sample code here, you can't use mutable, this is an indication that something might be wrong.
maybe it was optimized by the compiler. he have all rights to do this.
it is drawback of misusing const_cast.
never use const_cast in such way.