C++ Convert Address of Memory To Value? [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
In C++, using the iostream, you can print a variable's memory address. For example:
std::cout << &variable << std::endl;
// Example Result: 002AFD84
However, what if I wanted to store this memory address into a variable? Such as converting the memory address to a string or double(or int, etc.)? Or even convert that string or double(or int, etc.) back again, to a memory address?
I'd like to do this for various reasons, one being: This would allow me to return the memory address for data within a DLL to a program calling the DLL and it's functions. On top of this, I won't have to keep track of the data itself within the DLL, since the data could then be referenced by it's memory address.
I cannot use pointers in this particular situation due to constraints. The constraints being: The interpreted programming language I am using does not have access to pointers. Due to this, pointers cannot be used to reference the data outside of the DLL.
As a side question, what number format do memory addresses use? They seem to always seems to be 8 characters in length, but I can't figure out what format this is.

To convert a pointer into a string representation, you can use a string stream. These are similar to the standard I/O streams std::cin and std::cout, but write to or read from a string rather than performing I/O.
std::ostringstream oss;
oss << &variable;
std::string address = oss.str();
To convert a pointer into an integer that represents the same address, use reinterpret_cast. The type uintptr_t, if it exists, is guaranteed to be large enough to hold any pointer value. But I think usually it suffices to use unsigned long.
unsigned long address = reinterpret_cast<unsigned long>(&variable);
Converting a pointer into a floating-point type seems fairly useless. You would have to convert into an integral type first, then convert to a floating-point type from there.

If you absolutely need to do this I suggest being selective about what types you convert to. Arbitrarily converting pointers to non-pointer types can be problematic and introduce problems that are difficult to detect. This is especially true if you are using reinterpret_cast to perform the conversions. One of the more common issues is the size of the destination type between various platforms. When you use something like reinterpret_cast you typically don't get warnings about loss of precision during the conversion.
For situations require you to convert a pointer to an integral type I suggest wrapping these conversion in a function template. This will allow you a bit of flexibility in performing the conversion and can perform compile-time size checks to ensure the destination type is large enough to hold the pointer.
Something like the code below might be helpful.
template<class DestType, class SourceType>
DestType bubblicious_value_cast(const SourceType& src)
{
static_assert(sizeof(DestType) >= sizeof(SourceType), "Destination size is too small");
return reinterpret_cast<DestType>(src);
}
int main()
{
void* ptr = nullptr;
int val = bubblicious_value_cast<int>(ptr);
}

You can use reinterpret_cast like this:
uintptr_t address = reinterpret_cast<uintptr_t>(&variable);
In 64-bit (or 32-bit) environment memory address has 64-bit (32-bit) length, respectively.

Related

How does type conversion affect the memory accessed by the program and its variables? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
If I have the following code:
int variable = 65;
double variable2 = 54.34;
double sum = (double)variable + variable2;
So, in this case there will be 2 bytes allocated to variable. Again, if the variable is typecasted into a double variable. So it will be assigned an additional 8 bytes for its representation.
Pertaining to this, my question is that, will the variable, "variable" be assigned 10 bytes of memory, or am I getting something wrong?
(double)variable is an rvalue, so it doesn't formally have any storage.
At a level much lower than C++, the hardware platform's implementation of "addition of two doubles" might mean that it has to put a copy of variable in the bit-format of a double somewhere in memory so it can be added.
Probably the double bit-format of variable will end up in a the register of an FPU (Floating Point Unit) instead and so will never occupy "memory".
Either way, you can't get at that memory with C++. You would need to tell the compiler to put it somewhere, i.e. make it an lvalue, or use it in a way where the C++ standard requires that an an lvalue be created, e.g., passing it to a function
That's probably also true of the int bit-format of variable and of variable2, which (even though lvalues) the compiler will hopefully shove them off into (CPU or FPU) registers if you never use the lvalueness, so they won't appear in memory either.
The size of int is actually compiler specific, so you can't make any size assumptions about it unless you only work with one compiler. I would strongly recommend #including <cstdint> and using the u/intX_t types(i.e. int16_t, int32_t, int64_t) so you know the size of the type you're dealing with. They're aliases that map to whatever built-in types are necessary to achieve a given minimum size.
Cast behavior can vary depending on the type. In general all casts perform a conversion of some kind. It helps to think of casting as "converting", where the conversion rules depend on the type. Unless you're dealing with a custom cast operator, the conversion is going to promote, demote, transform, or reinterpret the bytes of the thing being casted from. Promotions (i.e. short => int) extend the bits depending on if it's signed or unsigned. Demotions (i.e. int => short) trim off the higher bits, leaving you with the low part. Transformations (i.e. int => double) convert from one format to another. Reinterpretations (i.e. int* => double*) treat the bits as if it were the casted to type.
Your code converts an int to a double and adds it to another double. This has the same effect as if you had left out the cast, because int is implicitly casted to double when used in an arithmetic expression like that.

assign `this` to `MyClass *instance`, `instance->member` is not referencing same memory as `this->member` [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
In my cpp implementation I have:
static MyClass *instance;
floating freely outside all containing scopes (curly {}). I've tried initializing it to nullptr too.
void MyClass::myMethod() {
instance = this;
LOG("Hello, %d, %d", wList, instance->wList);
The above log displays an arbitrary location for member object pointer wList but instance should be pointing to the same data that this does, and hence the same wList, but it doesn't. instance->wList is still 0. What's happening here?
As Mark Ransom noted in the comments, you can't use the %d format specifier to print a pointer, you must use %p in order for your code to be portable. It's technically Undefined Behavior to use anything besides %p for pointers, but in all likelihood you'll see that it will seem to work ok on 32-bit systems.
However, on 64-bit systems, which I'd wager you're using, it blows up. Pointers are 8 bytes, but printf only tries to read 4 bytes off of the stack when it sees %d. For the second %d specifier, it reads the next 4 bytes, which are the other 4 bytes of the pointer—if you're seeing 0 for that, it probably means that your pointer was allocated within the first 4 GB of memory on a little-endian system (i.e. its value was something like 0x00000000'xxxxxxxx). The 8 bytes on the stack from the second pointer passed to printf never get read.
The %p specifier portably prints a pointer on all platforms, regardless of whether they're 32 bits, 64 bits, or some other size. One unfortunate consequence of this is that the exact output format is implementation-defined, meaning it can and does change between systems. Some systems might use a leading 0x or 0X, while others might have no prefix at all and just print the raw hex value. Some might pad to the left with 0's, and others might not.
If you want to control the exact output, then you can use a format of your choice (e.g. %08x or %016llx) as long as you cast the pointer appropriately for that specifier. For example, here's how you would do that on 32- and 64-bit systems:
printf("0x%08x\n", (unsigned int)(uintptr_t)myPointer); // 32-bit
printf("0x%016llx\n", (unsigned long long)(uintptr_t)myPointer); // 64-bit
The reason for casting twice is to avoid spurious compiler warnings, since some compilers will complain if you cast from a pointer type to an integer type which isn't guaranteed to be large enough to hold a pointer.

Convert pointer to int and back to typed object

I need a simple way to convert a pointer to an int, and then back to the pointer. I need it as an int for portability, since an int is easier to carry around in my project than a pointer.
Start player and return pointer:
SoundPlayer* player = new FxPlayerTiny();
return (int)player; // this works, but is it correct?
Stop player using pointer int:
FxPlayerTiny* player = static_cast<FxPlayerTiny*>((int*)num); // this gives me an error
FxPlayerTiny* player = (FxPlayerTiny*)((int*)obj); // this works, but is it correct?
delete player;
The best thing to do is to fix your project so it can deal with pointers. Integers and pointers are two different things. You can convert back and forth, but such conversions can lose information if you're not careful.
Converting a pointer value to int and back again can easily lose information, depending on the implementation and the underlying platform. For example, there are systems on int is smaller than a pointer. If you have 32-bit ints and 64-bit pointers, then converting a pointer to an int and back again will almost certainly give you an invalid pointer.
It's very likely that long or unsigned long is wide enough to hold a converted pointer value without loss of information; I've never worked on a system where it isn't. (Personally, I tend to prefer unsigned types, but not for any really good reason; either should work equally well.)
So you could write, for example:
SoundPlayer* player = new FxPlayerTiny();
return reinterpret_cast<unsigned long>player;
and convert the unsigned long value back to a pointer using reinterpret_cast,SoundPlayer*>.
Newer implementations provide typedefs uintptr_t and intptr_t, which are unsigned and signed integer types guaranteed to work correctly for round-trip pointer-to-integer-to-pointer conversions. They were introduced in C99, and optionally defined in the <stdint.h> header. (Implementations on which pointers are bigger than any integer type won't define them, but such implementations are rare.) C++ adopted them with the 2011 standard, defining them in the <cstdint> header. But Microsoft Visual C++ does support them as of the 2010 version.
This guarantee applies only to ordinary pointers, not to function pointers or member pointers.
So if you must do this, you can write:
#include <cstdint>
SoundPlayer* player = new FxPlayerTiny();
return reinterpret_cast<std::uintptr_t>player;
But first, consider this. new FxPlayerTiny() gives you a pointer value, and you're going to want a pointer value. If at all possible, just keep it as a pointer. Converting it to an integer means that you have to decide which of several techniques to use, and you have to keep track of which pointer type your integer value is supposed to represent. If you make a mistake, either using an integer type that isn't big enough or losing track of which pointer type you've stored, the compiler likely won't warn you about it.
Perhaps you have a good reason for needing to do that, but if you can just store pointers as pointers your life will be a lot easier.
It is not recommended to use an int for portability, especially because sizeof (int) and sizeof (void*) could differ (for example when compiling for Windows x64).
If ints are needed for a user interface, it maybe would be better to use a table of pointers and accessing them via indices.
However, if you want to convert an pointer to an integer and vice versa a simple conversion is enough but it's just the same, if sizeof *int) == sizeof (void*).

Is this use of std::array undefined behavior? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Aliasing `T*` with `char*` is allowed. Is it also allowed the other way around?
I'm using a std::array of chars to hold a value of unknown primitive type, which is no more than 10 bytes long, like so:
std::array<char, 10> val;
*reinterpret_cast<double*>(val.data()) = 6.3;
//blah blah blah...
double stuff = *reinterpret_cast<double*>(val.data());
I have read that casting back and forth through char * is not undefined, because the compiler assumes a char * may alias a value of any type. Does this still work when the value is placed in (what I assume is) an array of chars inside the object?
Note: I am aware that I could be using a union here, but that would result in a large amount of boilerplate code for what I am doing, and I would like to avoid it if necessary, hence the question.
Yes, std::array< char, 10 > does not satisfy the alignment requirements of double so that reinterpret_cast provokes UB.
Try std::aligned_storage instead.
It doesn't matter what the array is contained in.
The standard does not even consider what surrounds something (it's that basic), but does support conversion to/from char sequences.
To do this directly via reinterpret_cast and assignment, you need to have the buffer correctly aligned.
An alternative is to use memcpy, which doesn't care about alignment.
On a related issue, it's generally not a good idea to go down to the binary level. For example, a simple version change of the compiler might make a file of binary-serialized data inaccessible. A main driver for doing this anyway is raw performance considerations.

What are the use pointer variables?

I've recently tried to really come to grips with references and pointers in C++, and I'm getting a little bit confused. I understand the * and & operators which can respectively get the value at an address and get the address of a value, however why can't these simply be used with basic types like ints?
I don't understand why you can't, for example, do something like the following and not use any weird pointer variable creation:
string x = "Hello";
int y = &x; //Set 'y' to the memory address of 'x'
cout << *y; //Output the value at the address 'y' (which is the memory address of 'x')
The code above should, theoretically in my mind, output the value of 'x'. 'y' contains the memory address of 'x', and hence '*y' should be 'x'. If this works (which incidentally on trying to compile it, it doesn't -- it tells me it can't convert from a string to an int, which doesn't make much sense since you'd think a memory address could be stored in an int fine).
Why do we need to use special pointer variable declarations (e.g. string *y = &x)?
And inside this, if we take the * operator in the pointer declaration literally in the example in the line above, we are setting the value of 'y' to the memory address of 'x', but then later when we want to access the value at the memory address ('&x') we can use the same '*y' which we previously set to the memory address.
C and C++ resolve type information at compile-time, not runtime. Even runtime polymorphism relies on the compiler constructing a table of function pointers with offsets fixed at compile time.
For that reason, the only way the program can know that cout << *y; is printing a string is because y is strongly typed as a pointer-to-string (std::string*). The program cannot, from the address alone, determine that the object stored at address y is a std::string. (Even C++ RTTI does not allow this, you need enough type information to identify a polymorphic base class.)
In short, C is a typed language. You cannot store arbitrary things in variables.
Check the type safety article at wikipedia. C/C++ prevents problematic operations and functional calls at compliation time by checking the type of the operands and function parameters (but note that with explicit casts you can change the type of an expression).
It doesn't make sense to store a string in an integer -> The same way it doesn't make sense to store a pointer in it.
Simply put, a memory address has a type, which is pointer. Pointers are not ints, so you can't store a pointer in an int variable. If you're curious why ints and pointers are not fungible, it's because the size of each is implementation defined (with certain restrictions) and there is no guarantee that they will be the same size.
For instance, as #Damien_The_Unbeliever pointed out pointers on a 64-bit system must be 64-bits long, but it is perfectly legal for an int to be 32-bits, as long as it is no longer than a long and nor shorter than a short.
As to why each data type has it's own pointer type, that's because each type (especially user-defined types) is structured differently in memory. If we were to dereference typeless (or void) pointers, there would be no information indicating how that data should be interpreted. If, on the other hand, you were to create a universal pointer and do away with the "inconvenience" of specifying types, each entity in memory would probably have to be stored along-side its type information. While this is doable, it's far from efficient, and efficiency is on of C++'s design goals.
Some very low-level languages... like machine language... operate exactly as you describe. A number is a number, and it's up to the programmer to hold it in their heads what it represents. Generally speaking, the hope of higher level languages is to keep you from the concerns and potential for error that comes from that style of development.
You can actually disregard C++'s type-safety, at your peril. For instance, the gcc on a 32-bit machine I have will print "Hello" when I run this:
string x = "Hello";
int y = reinterpret_cast<int>(&x);
cout << *reinterpret_cast<string*>(y) << endl;
But as pretty much every other answerer has pointed out, there's no guarantee it would work on another computer. If I try this on a 64-bit machine, I get:
error: cast from ‘std::string*’ to ‘int’ loses precision
Which I can work around by changing it to a long:
string x = "Hello";
long y = reinterpret_cast<long>(&x);
cout << *reinterpret_cast<string*>(y) << endl;
The C++ standard specifies minimums for these types, but not maximums, so you really don't know what you're going to be dealing with when you face a new compiler. See: What does the C++ standard state the size of int, long type to be?
So the potential for writing non-portable code is high once you start going this route and "casting away" the safeties in the language. reinterpret_cast is the most dangerous type of casting...
When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?
But that's just technically drilling down into the "why not int" part specifically, in case you were interested. Note that as #BenVoight points out in the comment below, there does exist an integer type as of C99 called intptr_t which is guaranteed to hold any poniter. So there are much larger problems when you throw away type information than losing precision...like accidentally casting back to a wrong type!
C++ is a strongly typed language, and pointers and integers are different types. By making those separate types the compiler is able to detect misuses and tell you that what you are doing is incorrect.
At the same time, the pointer type maintains information on the type of the pointed object, if you obtain the address of a double, you have to store that in a double*, and the compiler knows that dereferencing that pointer you will get to a double. In your example code, int y = &x; cout << *y; the compiler would loose the information of what y points to, the type of the expression *y would be unknown and it would not be able to determine which of the different overloads of operator<< to call. Compare that with std::string *y = &x; where the compiler sees y it knows it is a std::string* and knows that dereferencing it you get to a std::string (and not a double or any other type), enabling the compiler to statically check all expressions that contain y.
Finally, while you think that a pointer is just the address of the object and that should be representable by an integral type (which on 64bit architectures would have to be int64 rather than int) that is not always the case. There are different architectures on which pointers are not really representable by integral values. For example in architectures with segmented memory, the address of an object can contain both a segment (integral value) and an offset into the segment (another integral value). On other architectures the size of pointers was different than the size of any integral type.
The language is trying to protect you from conflating two different concepts - even though at the hardware level they are both just sets of bits;
Outside of needing to pass values manually between various parts of a debugger, you never need to know the numerical value.
Outside of archaic uses of arrays, it doesn't make sense to "add 10" to a pointer - so you shouldn't treat them as numeric values.
By the compiler retaining type information, it also prevents you from making mistakes - if all pointers were equal, then the compiler couldn't, helpfully, point out that what you're trying to dereference as an int is a pointer to a string.