1

If we ignore the aspects:

  1. Bad practice
  2. Unjustified need
  3. and probably others ...

What are the risks (run-time : crash, undefined behavior, segmentation fault. implementation-defined behavior : wrong address generation) of this program as long as the address remains in the interval INT_MIN and INT_MAX:

#include <iostream>
using namespace std;
#include <sstream> 
#include <string>  

#define TAB_SIZE 2

void UseIntAsAdress (unsigned int  i)
{
    int *pTab =  (int*) i;
    for (int i=0; i< TAB_SIZE; i++)
        cout << "tab ["<<i<<"] = "<< pTab[i] <<endl;
}

int main()
{
    int *pTab = new int [TAB_SIZE];
    for ( int i=0; i<TAB_SIZE; i++)
        pTab [i] = i; 

    std::stringstream streamAdr;
    streamAdr << pTab;  
    std::string name = streamAdr.str(); 

    unsigned int i = stoi(name.c_str(), 0, 16);

    UseIntAsAdress (i);

    delete [] pTab;
    return 0;
}
Landstalker
  • 1,368
  • 8
  • 9
  • What do you mean by _risks_? – Cubic Mar 07 '20 at 15:44
  • @Cubic in wich case thisi program can Crash or produce a segmentation fault, or undefined behaviour, or out of bound for example. – Landstalker Mar 07 '20 at 15:45
  • The primary risk here is that address will not remain in interval `INT_MIN` and `INT_MAX`... On modern x64 systems it is typically well outside of that range. You should use `::std::uintptr_t` if you want to pass some opaque address around as an integer. – user7860670 Mar 07 '20 at 15:49
  • On 64 bit system `sizeof(int) != sizeof(int *)`. You will loose upper part of the address. – Tarek Dakhran Mar 07 '20 at 15:50
  • Does this answer your question? [How do I cast a pointer to an int](https://stackoverflow.com/questions/14092754/how-do-i-cast-a-pointer-to-an-int) – Tarek Dakhran Mar 07 '20 at 15:51
  • The question explicitly asserts that the address fits into `int`. @Landstalker, maybe you can reformulate your question (replace `int` with a bigger integer type, e.g., `intptr_t`) to focus on the actual question? – pasbi Mar 07 '20 at 15:52
  • @user7860670 @Tarekdakhran, Thanks. Even for unsigned int (`UINT_MAX`) ? – Landstalker Mar 07 '20 at 15:53
  • you can not rely on an unsigned int to be 16 bits. thats one risk – MauriceRandomNumber Mar 07 '20 at 15:54
  • 2
    "If we ignore [the risks], what are the risks?" I think the most egregious issue is the lack of maintainability. "Why did Parva use an `int` here instead of a pointer or a `std::uintptr_t`? What am I missing?" – JohnFilleau Mar 07 '20 at 15:56
  • @pasbi `unsigned long long` for exemple ? – Landstalker Mar 07 '20 at 15:57
  • @John I agree for hard maintainability. but I'm wondering about the aspects: crash, undefined behavior, segmentation fault, ... – Landstalker Mar 07 '20 at 16:02
  • 1
    If you're only interested in potential run-time problems with this code then you need to specify that in the question. – JohnFilleau Mar 07 '20 at 16:04
  • Casting arbitrary integers to pointers == headache. Don't do that. – Jesper Juhl Mar 07 '20 at 16:16
  • If you can guarantee `sizeof(int) == sizeof(int*)`, then the risks are less (still dependent on implementation defined behavior). Sign propagation is one possible risk. If the sizes don't match, its DOA. – Eljay Mar 07 '20 at 16:18
  • it's more cleare now. Thank you all – Landstalker Mar 07 '20 at 16:27

1 Answers1

3

Your program has implementation-defined behavior. Both the result of streamAdr << pTab; and the result of (int*) i are implementation-defined.

So you need to look at the documentation of your particular compiler to figure out whether this program behaves in the way you expect it to or not.

There is no general guarantee that this will behave correctly.


The cast from pointer to integer can be done much simpler as well:

reinterpret_cast<std::intptr_t>(pTab)

This is assuming your implementation supports std::intptr_t. Otherwise (in particular pre-C++11) you can try one one of the standard integer types. Compilation should fail if the type used is too small to hold the pointer values and otherwise it will work the same as std::intptr_t.

If then the value resulting from this cast isn't narrowed by conversion to int, the result of casting back to int* will behave as expected (i.e. you get a pointer to the first element of the array back), otherwise it will still have implementation-defined behavior.

walnut
  • 21,629
  • 4
  • 23
  • 59
  • Thanks. Unfortunately my implementation does not support `std::intptr_t` – Landstalker Mar 07 '20 at 16:08
  • @Landstalker If you are working with some unusual architecture you might want to add that to the question. Also, you can use one of the standard integer types in place of `std::intptr_t`. If the type is too small to hold the pointer values, it should give a compilation error, otherwise it should work the same way I described. But as mentioned above it would be weird for it to not define `std::intptr_t` if such an integer type exists. – walnut Mar 07 '20 at 16:13
  • i'm talking about C++ version. i have a usual architecture. – Landstalker Mar 07 '20 at 16:17
  • @Landstalker ok, then try one of the standard integer types as I mentioned above. Also I suggest you add the corresponding C++ version tag to your question, because it is otherwise generally assumed that you have at least C++11 available. What I wrote in my answer otherwise applies pre-C++11 as well. – walnut Mar 07 '20 at 16:20
  • I update tag. Thanks. – Landstalker Mar 07 '20 at 16:25
  • @Landstalker You added the C++11 tag, but `std::intptr_t` has been introduced in C++11. If it is not available because of the standard version, you must be using C++98 or C++03. – walnut Mar 07 '20 at 16:27
  • 1
    I have missed an inlude, i can use `std::intptr_t`. and im on C++11. – Landstalker Mar 07 '20 at 16:34