-1

I am learning c++ and found POINTER is similar to an INTEGER, so I was curious if I could implement POINTER from LONG LONG, I know it's not a good idea though, but it will be fun to do so. Here my idea is to cast a pointer to int like data type (say xpointer), and then use xpointer to access and modify the content of address it contains if possible!

So in pursuit of doing it, I tried to store the POINTER in a LONG LONG type, but it overflowed, so rather got an error.

#include <iostream>
using namespace std;
int main()
{
    int x = 1923;
    long long xpointer;
    xpointer = (int)&x;
    cout << xpointer << endl;
    return 0;
}

I know POINTER is too large to store in LONG LONG so got an error here, could you suggest me a way to achieve the goal?

Here is the error message for reference.

error: cast from pointer to smaller type 'int' loses information
xpointer = (int)&x;
               ^~~~~~~
1 error generated.

PS: Here I did a mistake in, casting x to int rather than long long so it overflowed, apart from it, how can I use xpointer to modify or retrieve data back, like what we do using a pointer variable if possible?

rkscodes
  • 85
  • 7
  • Hint: you are trying to assign to a `long long`, not an `int` – Caleth Jul 11 '19 at 16:07
  • @Caleth thanks for pointing out, updated the changes :) – rkscodes Jul 11 '19 at 16:42
  • Possible duplicate of [Converting a pointer into an integer?](https://stackoverflow.com/q/153065/10933809) – Oblivion Jul 11 '19 at 16:43
  • Whenever a question like this comes up, I have to ask... Why do you want to do this? – Baldrickk Jul 11 '19 at 16:47
  • @Baldrickk I can totally understand that it's not required anyhow, but I would love to get a deeper sense to understand it much better. – rkscodes Jul 11 '19 at 16:53
  • Re: "POINTER is similar to an INTEGER" -- only if "similar" means "not at all like". They are two fundamentally different things. Yes, down in the hardware they look very much alike, but that's not the abstraction that C++ (or just about any other programming language) presents. – Pete Becker Jul 11 '19 at 18:49

3 Answers3

4

The essence of your problem is that your code is designed to shoot yourself in the foot, and you're misinterpreting the foot wound as a natural cause.

For example, in the environment you're compiling for, long long actually is large enough to store a pointer†, so there's no reason you couldn't write code like this:

int x = 1923;
long long xpointer;
xpointer = reinterpret_cast<long long>(&x); //Valid on a 64-bit x86 CPU compiled with GCC
cout << xpointer << endl; 
return 0;

But your code is instead the equivalent of xpointer = reinterpret_cast<int>(&x);, which is not valid in your environment. int is not the same size as long long†, and if you're casting to the latter, you need an express cast to that type. Not to an intermediate type (int) that then gets implicitly expanded to the proper type (long long), which will instead cause a warning or error.

In the future, if you do intend to store a pointer as an integer, you should prefer std::intptr_t instead, as [iff that type is defined for your environment] it is guaranteed to be large enough to store a pointer as an integer.

int x = 1923;
intptr_t xpointer = reinterpret_cast<intptr_t>(&x); //Guaranteed to be valid if intptr_t is defined
cout << xpointer << endl; 
return 0;

†Be aware that not all environments have the same sizes of integers (including int and long long) as GCC on a 64-bit x86 environment. In your case, that's 32-bits and 64-bits respectively, but those numbers, especially the former, may be different if you are instead compiling for a different environment.


If you then intend to actually use the pointer stored in xpointer to modify the data it points to, you need to then cast the pointer back. You cannot manipulate the data pointed to by xpointer without instructing the compiler to treat it as a pointer.

int x = 1923;
intptr_t xpointer = reinterpret_cast<intptr_t>(&x);
cout << xpointer << endl; 
int* ptr = reinterpret_cast<int*>(xpointer); //Legal If-and-only-If xpointer has not been changed
*ptr = 2019;
cout << x << endl; //Should print "2019"
cout << *ptr << endl; //Should print "2019"
return 0;

Be warned though that if you attempt to perform any kind of arithmetic operation on the pointer itself, you'll quickly veer into Undefined Behavior territory, and the behavior of your program can no longer be guaranteed:

int x = 1923;
intptr_t xpointer = reinterpret_cast<intptr_t>(&x);
cout << xpointer << endl; 
int* ptr = reinterpret_cast<int*>(xpointer); //Legal If-and-only-If xpointer has not been changed
*ptr = 2019;
cout << x << endl; //Should print "2019"
xpointer++;//Legal, but...
int* ptr2 = reinterpret_cast<int*>(xpointer); 
*ptr2 = 2020; //This is now undefined behavior
cout << x << endl; //Legal on its own, but because of preceeding undefined behavior,
//this may not do what you expect.
return 0;
Xirema
  • 19,889
  • 4
  • 32
  • 68
  • Ok my bad, I got it. But how can I perform operations like access and modification of int `x` using `xpointer` var in this case if possible? – rkscodes Jul 11 '19 at 17:08
  • I would like to know if using `xpointer` var can I retrieve and modify var `x` or not, I don't want to cast it back, otherwise why I would have cast at first place? – rkscodes Jul 11 '19 at 17:22
  • @codeitram As stated in the second part of my answer, it's not possible to modify the pointed-to data using `xpointer`. There's simply no construct to do so in C++: it has to be cast to a pointer (or reference) first. The reason *why* you might do something like this is if `xpointer` was provided by a third-party API, and you didn't cast `x` to `xpointer` yourself in the first place. – Xirema Jul 11 '19 at 17:27
  • @codeitram Just so you're aware, though: `reinterpret_cast` does not invoke any CPU instructions at all; it's just an instruction to the compiler on how the data should be interpreted. – Xirema Jul 11 '19 at 17:27
-1

int is (in modern compilers) 32 bits. A pointer is 32 or 64 bits. Your compilation is probably with the 64 bit compiler, hence the error between int and int*.

Apart from that, C++ is a strongly typed language, or we could simply write it in assembly and forget about types.

int is not the same as a pointer, long long is not the same as a pointer. You would need ugly C style casts.

Suggestion, read a good book.

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78
-1

In standard C++, intptr_t is an integral type that is guaranteed to be large enough to hold a pointer. If you want to store an address in an integer, use that.

Joe
  • 5,394
  • 3
  • 23
  • 54
  • 1
    You got downvoted because your answer doesn't actually address the root issue the OP is having. `long long` is perfectly large enough to hold a pointer [on their environment], but they've made a mistake with their type casting that's causing their error. – Xirema Jul 11 '19 at 16:08
  • 1
    Ha again. Correct. My bad. – Joe Jul 11 '19 at 16:10