Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to cast an int to void pointer and back to int again?

Tags:

c++

c

pointers

In C and/or C++: is it safe to cast an int to void pointer and back to int again?

Based on the question "C++: Is it safe to cast pointer to int and later back to pointer again?".

like image 775
Lesmana Avatar asked Aug 25 '10 16:08

Lesmana


6 Answers

In most modern-day commonplace machines, probably.

However, I'd bet that there is some obscure compiler or configuration (say, a 16-bit addressed machine that uses 32-bit integer arithmetic) where that is not the case.

A uintptr_t is guaranteed to hold both, though, so use that type if you want to.

like image 188
Steven Schlansker Avatar answered Oct 01 '22 22:10

Steven Schlansker


Here is an example where converting a pointer to an integer may not result in the same pointer when converting the integer to a pointer.

Given an architecture which has 24 bit addresses and uses two 16-bit quantities to describe the location. Let one quantity be the SEGMENT and the other OFFSET. A location is designated by the notation SEGMENT:OFFSET.

The actual 24-bit (Physical) address is calculated by:

address = segment * 16 + offset.

Using this notation, there can be more than one SEGMENT:OFFSET pair that describe the same physical address.

When converting to an integer, a 32-bit (unsigned) quantity is used (to simplify internal calculations in the processor). The problem is how to convert the physical address into the same SEGMENT::OFFSET that was used in the creation of the physical address.

A generic equation for converting integer to pointer is:

offset = address & 0xFFFF; // Mask off high order bits, keep lower 16.
segment = address >> 16;   // Shift address right 16 bits, zero fill.

Although the physical address of this new segment and offset is equal to the physical address of the original SEGMENT:OFFSET, the segments and offsets are not guaranteed to be the same.

To optimize code, there are processor instructions that use relative addressing in a segment. These instructions may get messed up when the SEGMENT value changes due to conversion from a physical address.

In this scenario, converting from a pointer to an integer is possible. HOWEVER, converting from the integer to the pointer IS STRONGLY DISCOURAGED. Hard to debug errors could occur during run-time.

Bonus question: Can you name the actual architecture?

like image 32
Thomas Matthews Avatar answered Oct 01 '22 21:10

Thomas Matthews


Why would you want to do this?

Reply for C, I don't know enough about C++ for that: No, behavior is not defined to cast an int to void*. First of all you should always use uintptr_t if you have it for such a thing. Using int is an abuse.

Then, C does not guarantee anything if your uintptr_t doesn't come from a valid address. It only guarantees the other way round. Don't do it.

Edit: Here is the relevant part of the C99 standard. As you can see all alarms can go off...

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation

The last is particularly embarrassing since this means that the pointer value that is such obtained can not be used anymore, until it is overwritten:

Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. ... Such a representation is called a trap representation.

like image 25
Jens Gustedt Avatar answered Oct 01 '22 21:10

Jens Gustedt


No. A void pointer is no different from any other pointer with respect to size. Hence it will run into exactly the same types of issues as other pointer types.

like image 29
JaredPar Avatar answered Oct 01 '22 22:10

JaredPar


It's implementation defined just like the last question and for the same reason. It's less likely to result in misbehavior but it's still implementation defined.

like image 34
Edward Strange Avatar answered Oct 01 '22 20:10

Edward Strange


No. There might be certain circumstances where it appears to work for a certain compiler&settings, and then two years later you spend weeks debugging that something changed and the conversion no longer works as expected.

If you just design your code in a way that doesn't need this sort of behavior (best case avoids use of such conversion at all, worst case use char[]) then you won't have to worry about obscure bugs in the future.

like image 35
Mark B Avatar answered Oct 01 '22 20:10

Mark B