2

consider this code

T* pa = new T(13);
int address = reinterpret_cast<int>(pa);

Where T can be any built-in type.

1) I can not understand what's wrong with reinterpret cast here ??

2) What are the cases when this kind of casting will lead to an undefined behavour ?

3) Will pa always contain the correct decimal representation of a memory address ?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
ampawd
  • 968
  • 8
  • 26
  • 1
    ints and pointers are not required to be the same size –  Sep 09 '17 at 19:22
  • If `1 << (sizeof(T*) * CHAR_BIT)` is greater than `INT_MAX`, then the value of your address might not fit in the `int`. – Cornstalks Sep 09 '17 at 19:23
  • @NeilButterworth okay, lets say address is big enough to contain that hex value, lets say its long long – ampawd Sep 09 '17 at 19:25
  • Typically `sizeof(int) < sizeof(T *)`, so the value of "address" will not be able to represent the value of `pa`. As long as you only print `address` for your amusement it will be fine, but as soon as you want to use it for something useful you can't. – nwp Sep 09 '17 at 19:25
  • @Cornstalks Ah yes, I got confused there for a sec. Thanks :) – Rakete1111 Sep 09 '17 at 19:26
  • 2
    Also, [`[u]intptr_t`](http://en.cppreference.com/w/c/types/integer) exists for this very purpose. – Cornstalks Sep 09 '17 at 19:27

3 Answers3

5

I can not understand what's wrong with reinterpret cast here?

Because ints and pointers are not required by the standard to have the same size, thus you might lose information by casting.

What are the cases when this kind of casting will lead to an undefined behavior?

When this is true:

1 << (sizeof(T*) * CHAR_BIT) > INT_MAX

then the value of the address might not fill in an int, which invokes Undefined Behavior.

Will pa always contain the correct decimal representation of a memory address ?

If you use std::[u]intptr_t, then yes, since these types are guaranteed to be able to hold the value of a pointer.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • 1
    minor nitpick: you are linking the C reference, not the C++ one – UnholySheep Sep 09 '17 at 19:39
  • 1
    I actually meant [this one](http://en.cppreference.com/w/cpp/types/integer) (since it contains information that this type is only part of the standard since C++11 and is also optional) – UnholySheep Sep 09 '17 at 19:42
  • so the std::[u]intptr_t will always have bigger or equal size than the pointer type ? – ampawd Sep 09 '17 at 19:48
  • @ampawd it will have the size need to store the value of a pointer, so basically yes... – gsamaras Sep 09 '17 at 19:48
  • 1
    @gsamaras there's no such reasons, thats the most informative answer – ampawd Sep 09 '17 at 20:07
  • As someone that knows little about C++ types, Is there any reason to use `intptr_t` over `int64_t`? – Nick is tired Sep 09 '17 at 20:13
  • 2
    @NickA - It depends on how portable you want to be. Some systems don't have an `int64_t` [like this one](https://stackoverflow.com/a/6972551/597607). – Bo Persson Sep 10 '17 at 01:29
2

The size of T* and int depends on your compiler and architecture.

If sizeof(T*) > sizeof(int) you'll discard information. While this might be true on one compiler and architecture might not be true on another.

You can use either std::intptr_t or std::uintptr_t instead of int. These two are guaranteed to be big enough to hold the value of a pointer.

such
  • 583
  • 4
  • 9
1

As other answers have pointed out, the size of an integer and the size of a pointer don't have to be the same. For example, on many 64-bit Intel machines a pointer is 64 bits and an integer is only 32.

There are other reasons to prevent this as well, though. For example, some older processor architectures have integer representations that include trap representations that result in undefined behavior if used. This means that in principle a pointer could fit into the size of an integer, but casting a pointer to an integer could result in a trap representation that causes further numeric calculations to fail.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065