I realized, what if i define const int into the body of c++ function and then use the address arithmetic to change the value of the constant( its on the stack, isn't it? ). i got this code:
const int a = 10;
int b = 100;
int * c = &b;
c++;
cout << "&a: " << &a << endl;
cout << " c: " << c << endl;
*c = 100500;
cout << " a: " << a << endl;
cout << "*c: " << *c << endl;
and i got this output
&a: 0x7ffff63866a8
c: 0x7ffff63866a8
a: 10
*c: 100500
So, addresses are the same, but values are different. Can someone explain me this result? Thanks!
p.s. i tried on GCC, Clang and VS
Can someone explain me this result?
As with any attempt to access objects in invalid ways via invalid pointer arithmetic or other shenanigans: undefined behaviour.
What is happening here is that the compiler is assuming that the value of a won't change, and optimising it to be a compile-time constant. It's allowed to do that, since you've declared it const and thereby stated that it won't change.
its on the stack, isn't it?
Since you also take the address of it (when you print &a), it does get allocated an address on the stack; but there's no need for the program to read from that address to get the value, since it's already known to be 10.
Of course, this is all undefined, so the program would be just as valid if it ordered you a pizza instead.
Your program has undefined behavior written all over it...
The assumption that incrementing the address of b will get you to a is bogus, it could or it could not. You are then using what is called in the standard unsafely derived pointer to modify a const object (a) which is also undefined behavior. Anything can happen.
What really happens (in your implementation, explanation of your results but you cannot depend on this as this is undefined behavior) is that you forced the allocation of a in the stack by means of taking its address, and you got a pointer into it. You modified that value, and the address in memory is updated. But, in the expression: cout << " a: " << a << endl; the compiler knows that a is a constant, and thus its value can only be 10, so it transformed the code into cout << " a: " << 10 << endl; to avoid having to go to memory to obtain the value.
const int a = 10;
int b = 100;
OK.
int * c = &b;
OK, but silly and my bug-o-meter is starting to twiddle.
c++;
Bug-o-meter now in the yellow zone.
cout << "&a: " << &a << endl;
OK
*c = 100500;
Bug-o-meter pegged. Undefined Behavior invoked. World explodes, you get fired.
c++ moves the pointer to the next int in memory. The pointer math is OK, but all you can use c for at this point is to compare the pointer to another pointer. You can't dereference the pointer in any way. But that's what you do when you try to assign through it.
What happens next is irrelevant and, honestly, misleading. You think that c now points to the same memory as b, and maybe it does. But it's only through Undefined Behavior that this happened. You might also think that the value of *c is what you expect it to be, but this result is false. Maybe it is, maybe it isn't. You shattered the vial when you opened the box -- the cat is dead. And so is your program.
And by the way, if what you're trying to do is find a way to cheat the compiler so that you can change a const, don't -- it is strictly forbidden to change a const by any means.
There is a const_cast in C++, but that is also not a mechanism that you can use to change a const.
its on the stack, isn't it?
No, your expectations are wrong. C++ has no notion of stack whatsoever, much less of how different automatic variables are stored in memory relative to each other. What you are trying to do is plain Undefined Behaviour.
In your very case, the compilers optimize a away, because they are allowed to by the standard, and the results you're getting don't have to make any sense since it's UB anyway.
The C++ compiler will simply assume that you will never try to change the value of a const variable.
This doesn't mean that if you do you will get an error... just that the compiler authors can ignore what is going to happen and anything that happens will be classified as "your fault".
SSCC:
#include <stdio.h>
int main ()
{
const int a = 10;
int b = 100;
int *c = &b;
printf ("a=%d, b=%d, *c=%d; &a=%p, &b=%p, c=%p\n",
a, b, *c, (void *)&a, (void *)&b, (void *)c);
c++; // "c" now invalid
printf ("a=%d, b=%d, *c=%d; &a=%p, &b=%p, c=%p\n",
a, b, *c, (void *)&a, (void *)&b, (void *)c);
*c = 100500; // Undefined behavior!
printf ("a=%d, b=%d, *c=%d; &a=%p, &b=%p, c=%p\n",
a, b, *c, (void *)&a, (void *)&b, (void *)c);
return 0;
}
EXAMPLE OUTPUT:
a=10, b=100, *c=100; &a=0028FF18, &b=0028FF14, c=0028FF14
a=10, b=100, *c=10; &a=0028FF18, &b=0028FF14, c=0028FF18
a=10, b=100, *c=100500; &a=0028FF18, &b=0028FF14, c=0028FF18
CASE 2 - WE DON'T TRY TO TAKE ADDRESSOF CONST A:
#include <stdio.h>
int main ()
{
const int a = 10;
int b = 100;
int *c = &b;
printf ("a=%d, b=%d, *c=%d; &b=%p, c=%p\n",
a, b, *c, (void *)&b, (void *)c);
c++; // "c" now invalid
printf ("a=%d, b=%d, *c=%d; &b=%p, c=%p\n",
a, b, *c, (void *)&b, (void *)c);
*c = 100500; // Undefined behavior!
printf ("a=%d, b=%d, *c=%d; &b=%p, c=%p\n",
a, b, *c, (void *)&b, (void *)c);
return 0;
}
SAMPLE OUTPUT
a=10, b=100, *c=100; &b=0028FF14, c=0028FF14
a=10, b=100, *c=2686744; &b=0028FF14, c=0028FF18
a=10, b=100, *c=0; &b=0028FF14, c=00018894
Related
I am failed to understand this to deep details as to why program1 would segfault and program2 would not.
program1:
void cpy(char* p, char* q) {
while(*p++ = *q++);
}
int main() {
char* p;
char* q = "Bhargava";
cpy(p, q);
std::cout << "p = " << &p << std::endl;
}
Program2:
void cpy(char* p, char* q) {
while(*p++ = *q++);
}
int main() {
char* p;
char* q = "Bhargava";
cpy(p, q);
std::cout << "p = " << p << std::endl;
}
What is the harm while printing the address of the variable 'p' here in program1?
Both programs have undefined behavior already at the call
cpy(p, q);
because p is of type char* and default-initialized with automatic storage duration, meaning that its value is indeterminate. Copying an indeterminate value (here into the function parameter) that is not of type std::byte or unsigned narrow character type has already undefined behavior.
The arithmetic on and dereferencing of this indeterminate value in cpy then continues to cause operations with undefined behavior, which is probably of more practical relevance than the undefined behavior mentioned above, given that it is clear that if p is considered to have some random value, accessing the memory at that random address should not be allowed by the operating system (the cause of a segmentation fault).
Undefined behavior means that you have no guarantee on the program behavior. The program might fail with an error or it might not and it might produce seemingly correct output or it might not.
In practice, the compiler is probably optimizing away the dereferencing of p in one of the programs, but not the other, so that there never will be memory access in the compiled program that will cause the segmentation fault, but as mentioned above you have no guarantees and the compiler can output anything.
The line
char* q = "Bhargava";
is not allowed since C++11 and should at least be producing a compiler diagnostic to that effect. Even before C++11, it was always deprecated in standard-C++. "Bhargava" has type const char[N] for some N, so it can be assigned to const char*, but not to char*. The latter was just allowed by the language initially for backwards-compatibility reasons with C.
Both programs exhibit Undefined Behavior because p is not pointing at any valid memory, its value is uninitialized and thus indeterminate, so calling cpy() with p as the destination will write to random memory, if not just crash outright.
That being said, the reason why << &p works is because &p is the address of the p variable itself, which is a valid address. The type that &p returns is char**, which operator<< does not have a specific overload for, but it does have an overload for void*, which char** is implicitly convertible to. That overload simply prints out the address as-is.
The reason why << p does not work is because operator<< does have a specific overload for char*. That overload treats the address as the start of a C-style null-terminated string, and will print out characters starting at the address until a '\0' character is reached. But, since p does not point to a valid C string, the behavior is undefined.
To make both programs work correctly, you need to do this instead:
Program1:
void cpy(char* p, const char* q) {
while(*p++ = *q++);
}
int main() {
char buffer[10];
char* p = buffer;
const char* q = "Bhargava";
cpy(p, q);
std::cout << "p = " << &p << std::endl;
}
Program2:
void cpy(char* p, const char* q) {
while(*p++ = *q++);
}
int main() {
char buffer[10];
char* p = buffer;
const char* q = "Bhargava";
cpy(p, q);
std::cout << "p = " << p << std::endl;
}
int main()
{
int a = 2; // address is 0x7ffeefbff58c
int *b = &a;
std::cout << "address of a: " << b << std::endl;
return 0;
}
I have my int variable a at address 0x7ffeefbff58c, but can I directly assign int* b with 0x7ffeefbff58c?
I tried int * b = 0x7ffeefbff58c;
But there is an error says "cannot initialize a variable of type 'int *' with an rvalue of type 'long'", so do I have to use the address of a (&a) to initialize the pointer? or there is other way to do it?
can I directly assign int* b with 0x7ffeefbff58c?
Technically, yes.
If so, how to do that?
With reinterpret cast.
But do realise that there is absolutely no guarantee in general that a would be in the address 0x7ffeefbff58c. As such, there isn't much that you can do with such integer reinterpreted as a pointer. Doing this with a local variable would be pointless.
A case where interpreting integer as a pointer is useful is some embedded systems that reserve some constant memory addresses for special purposes.
Heere is an example:
#include <iostream>
int main()
{
int *b = (int*) 0x7ffeefbff58c;
std::cout << "b: " << b << std::endl;
return 0;
}
after compilation and execution you will see output:
b: 0x7ffeefbff58c
So i want to point a pointer to a character and then output the address put it outputs this weird thing: t+ a. Any help?
#include <iostream>
using namespace std;
int main() {
char a = 't';
char* p = &a;
cout << p;
return 0;
}
You are printing a char* type, which the cout tries to interpret as a string.
Print the value of the pointer (The address it points to) using:
cout << (void *)p;
-- OR --
cout << static_cast<void *>(p);
The problem is that char * is conventionally not just used as a pointer to a char, but a pointer to a null-terminated C-string instead. cout will then print all the characters pointed to by p until it finds a '\0', so you get to see the t and then it prints invalid memory which is undefined behavior which may crash or print garbage or something else.
The way to fix this is to use void * or maybe const void * instead which is just a pointer with an address but no type information attached. void *p = &a; would be one fix. void *p2 = p; and then using std::cout << p2; would be another. You can also use a cast as shown in the other answer, except you should be using a C++ cast like static_cast<const void*>(p) instead of a C cast like (void *)p because once you get used to them they become easier to read and reason about.
If you want address of the pointer, either cast it to void pointer
std::cout << (void *)p;
or use printf with %p option
printf("%p", p);
Otherwise it will be treated as null terminated string, which it is not.
This question already has answers here:
Weird Behaviour with const_cast [duplicate]
(2 answers)
Closed 5 years ago.
const int *a = new int(100);
int *ptr = (int*) a;
cout << *a << endl;
*ptr = 1000;
cout << *a << endl;
const int b = 100;
int *c = (int*)&b;
*c = 200;
cout << &b << " " << b << endl;
cout << c << " " << *c << endl;
print out
While I use *ptr, I can change the const data *a. Why?
Both the address of b and *c are the same, but the data are different. Why?
While I use *ptr, I can change the const data *a. Why?
Because your program is causing undefined behavior. You lied to the compiler that b is non-const by casting const-ness away from the pointer produced by &b, but writing to that pointer on the *c = 200 line is undefined behavior.
Both the address of b and *c are the same, but the data are different. Why?
It happens for the same reason: the behavior is undefined.
As for the real-life scenario when this would happen, I would speculate that the compiler has optimized out the read of b, because you promised it that b is const. However, the compiler found a clever way of getting back at you by replacing a read of the actual b with the output of a constant that has been assigned to b originally.
I have a problem with the pointers. I know what this does:
*name
I understand that this is a pointer.
I've been searching but I do neither understand what this one does nor I've found helpful information
**name
The context is int **name, not multiplication
Could someone help me?
NOTE: Without the proper context, the usage of *name and **name is ambiguous. it may portrait (a). dereference operator (b) multiplication operator
Considering you're talking about a scenario like
char * name;
char **name;
in the code,
*name
name is a pointer to a char.
**name
name is a pointer, to the pointer to a char.
Please don't get confused with "double-pointer", which is sometimes used to denote pointer to a pointer but actually supposed to mean a pointer to a double data type variable.
A visual below
As above, we can say
char value = `c`;
char *p2 = &value; // &value is 8000, so p2 == 8000, &p2 == 5000
char **p1 = &p2; // &p2 == 5000, p1 == 5000
So, p1 here, is a pointer-to-pointer. Hope this make things clear now.
It's actually very simple, consider this:
int a; // a is an int
int* b; // b is a pointer to an int
int** c; // c is a pointer to a pointer to an int
If you see every level as just another variable type (so, see *int as a type), it's easier to understand.
Another example:
typedef int* IntPointer;
IntPointer a; // a is an IntPointer
IntPointer* b; // b is a pointer to an IntPointer!
Hope that helps!
pointer stores address of variable, pointer to pointer stores address of another pointer.
int var
int *ptr;
int **ptr2;
ptr = &var;
ptr2 = &ptr;
cout << "var : " << var;
cout << "*ptr : " << *ptr;
cout << "**ptr2 : " << **ptr2;
You can look here
int a = 5;// a is int, a = 5.
int *p1 = &a; // p1 is pointer, p1 point to physical address of a;
int **p2 = &p1; // p2 is pointer of pointer, p2 point to physical adress of p1;
cout<< "a = "<<a << " *p1 = "<<*p1<<" *(*p2) = " << *(*p2)<<endl;
**name in this case. Would be a pointer to a pointer.