Im currently experimenting with pointers and i have several questioins to my code
ps. this is just for experimenting Im not going to use this in any code
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
struct obj
{
int* IntPtr;
obj()
{
IntPtr = new int[2];
IntPtr[0] = 123;
IntPtr[1] = 456;
}
};
int main()
{
obj MyStruct;
long long int* Adress = (long long int*) & MyStruct; //pointer to a struct
//change value in struct
*(long long int*)(*Adress sizeof(int)) = 789;
std::cout << "get value by pointer: " << (int)*(long long int*)(*Adress sizeof(int)) << std::endl; //std::cout crashes my program
printf("get value by pointer: %d\n", (int)*(long long int*)(*Adress sizeof(int)));
printf("get value from struct: %d\n", MyStruct.IntPtr[1]);
return 0;
}
why does std::cout crashes my program? I had to use printf function to fix this issue
can i delete IntPtr from from my main function? something like
delete[] (long long int*)*Adress;
and then create new ? like:int* Itemp = new int[5]; *Adress = (long long int)Itemp;
EDIT: this was just an experiment on how to access int* IntPrt
in strcut obj
when it is private:
i wouldnt use this method othersise.
the code even with the delete[]
and new
worked fine on my compiler
thanks everyone for the explanation
CodePudding user response:
Even if the syntax errors in your code were fixed, the premise of what I suspect you are trying to do would still be fundamentally flawed. Taking a pointer, converting it to a number representing a memory address, shifting it around to land on another object and accessing it this way is simply not something you are allowed to do in C .
Compilers are allowed to, and actively do, optimize code based on the assumption that the program never does such things. So even if a program appears to be working while doing this, it could very well break when compiled with a different compiler, a different version of the same compiler, or different compilation settings on the same compiler.
So what does that mean to us as programmers? Pointers being memory addresses does not mean that we are allowed to treat them like memory addresses (with a few specific exceptions).
Pointers point to objects (reminder: even a simple int
is an object). the fact that a pointer points into memory is an implementation detail; unless you are manipulating the raw bytes of the underlying storage a single byte at a time.
You must treat a pointer as either:
Not pointing at an object, in which case you can only assign, copy, or compare it.
Pointing at an object, in which case you can also dereference it with
*
or->
.Pointing at an object that is part of an array, at which point, you can also use
[]
or pointer arithmetic (-
, etc...) to access other objects in the same array.
That's all.
Taking this into consideration, here's what your code should be looking like. This is mostly for reference. I know that's not what you were trying to do.
struct obj
{
int* IntPtr;
obj()
{
IntPtr = new int[2];
IntPtr[0] = 123;
IntPtr[1] = 456;
}
~obj()
{
// Btw. If you have a new, ALWAYS have a delete, even in throwaway code.
delete IntPtr[];
}
};
int main()
{
obj MyStruct;
// Get a pointer to the struct
obj* Adress = &MyStruct;
// Change value in struct via the pointer
obj->IntPtr[1] = 789;
(*obj).IntPtr[1] = 789;
std::cout << "get value by pointer: " << obj->IntPtr[1] << std::endl;
printf("get value by pointer: %d\n", obj->IntPtr[1]);
printf("get value from struct: %d\n", obj.IntPtr[1]);
}
Edit: For completeness' sake, here's code that does what I interpreted you were going for:
#include <iostream>
#include <cstdint>
#include <cassert>
struct obj {
int IntData[2];
};
int main()
{
obj MyStruct;
// Get a number containing the memory address associated with MyStruct.
// std::uintptr_t is the integer type of the same size as a pointer
std::uintptr_t AdressOfMyStruct = (std::uintptr_t)&MyStruct;
std::cout << "MyStruct lives at: " << AdressOfMyStruct << std::endl;
// Do the same thing for IntData[1]
std::uintptr_t AdressOfIntData1 = (std::uintptr_t)&MyStruct.IntData[1];
std::cout << "MyStruct.IntData[1] lives at: " << AdressOfIntData1 << std::endl;
// recalculate the address of IntData1 as an offset from MyStruct
std::uintptr_t AdressOfIntData1Calculated = AdressOfMyStruct sizeof(int);
std::cout << "MyStruct.IntData[1] lives at (alt): " << AdressOfIntData1 << std::endl;
// Verify that IntData[1] is where we expect it to be.
assert( AdressOfIntData1Calculated == AdressOfIntData1 );
// ...Everything up to here is valid code...
// WARNING: this may looks like it works, but it is, in fact, Undefined Behavior.
int* PtrToIntData1 = reinterpret_cast<int*>(AdressOfIntData1);
*PtrToIntData1 = 789;
// WARNING: This is also undefined behavior.
std::cout << "get value by pointer: " << *PtrToIntData1 << std::endl;
// This is fine, obviously.
std::cout << "get value from struct: " << MyStruct.IntData[1] << std::endl;
return 0;
}