22

I know the reinterpret_cast in C++ can be used in this way:

float a = 0;
int b = *reinterpret_cast<int*>(&a);

But why cannot cast it directly?

float a = 0;
int b = reinterpret_cast<int>(a);

error: invalid cast from type 'float' to type 'int'
sunlight07
  • 686
  • 1
  • 7
  • 21
  • None of those will compile with my gcc 4.8.1. Does it compile for you, or why asking? – László Papp Aug 31 '13 at 05:35
  • 1
    `(*)reinterpret_cast(&a);` can you explain what are you trying to do with this? – Deepak Ingole Aug 31 '13 at 05:37
  • 1
    int b = reinterpret_cast(a); will work, I tried that before. – László Papp Aug 31 '13 at 05:37
  • Are you sure it's not `static_cast(a)` you're looking for in the second case? I can't think of a single valid use of `reinterpret_cast` that does not involve a pointer or reference as either source or destination type. – Joachim Isaksson Aug 31 '13 at 05:44
  • @JoachimIsaksson If I use static_cast, the bits in the memory may change but the value of b will not change. If I use interpret_cast, the bits in the memory will not change, but the value of b may change. – sunlight07 Aug 31 '13 at 05:46
  • Just say "piss on it" and use this: `b = (int)a;` ;) But yeah - if you want to convert a float to an int (preserving/truncating value; changing bits) you want a static_cast<>. If you want to preserve the bits, then you need a reinterpret_cast<>... but there needs to be a pointer involved. – paulsm4 Aug 31 '13 at 05:58
  • IMHO - When people start using casts they are usually doing something wrong. Just use them sparingly and with caution. – Ed Heal Aug 31 '13 at 06:23
  • 3
    @DeepakIngole Isn't it obvious what the OP wants? Why would anyone do that? To get at the underlying bit pattern of the float to directly inspect the mantissa, exponent or sign bit. What else? And the question is: why does it have to be that complicated with all that pointer stuff? (BTW The best solution to achieve this with much hassle is `int b = reinterpret_cast(a);` which only appears in lpapp's answer which unfortunately isn't accepted). – Elmar Zander Oct 19 '21 at 07:07

5 Answers5

44

All reinterpret_cast does is allow you to read the memory you passed in a different way. You give it a memory location and you ask it to read that memory as if it was what you asked it to. This is why it can only be used with pointers and references.

Let's take this code as an example:

#include <iostream>

int main()
{
    float a = 12;
    int b = *reinterpret_cast<int*>(&a);

    std::cout << b;
}

So to break this line of code into more details *reinterpret_cast<int*>(&a);:

  1. Take the address of a
  2. reinterpret_cast to an int*
  3. Get back an int* that points to a
  4. Dereference the value of the returned pointer as int

Now when I run this I get 1094713344, the reason for that is 12 as a float using IEEE is represented as 0100 0001 0100 0000 0000 0000 0000 0000 in binary. Now take that binary and read it as int, then you end up with 1094713344.

This is why reinterpret_cast is considered to be very dangerous and why it should NOT be used in this type of cases.

You should only use it when you have a pointer pointing to memory and you need to read that memory in a certain way and you know that the memory can be read in that way.

starriet
  • 2,565
  • 22
  • 23
Caesar
  • 9,483
  • 8
  • 40
  • 66
  • Yes, I know the effect of reinterpret_cast. But I don't know why cannot cast it directly? – sunlight07 Aug 31 '13 at 06:47
  • @sunlight07 As I said, it was designed so that you can't because you shouldn't be doing it that way. – Caesar Aug 31 '13 at 06:52
  • So why reinterpret_cast works perfectly if I have to use it on a pointer? – sunlight07 Aug 31 '13 at 06:56
  • 6
    @sunlight07 `reinterpret_cast` allows you to cast pointers and references. Even if C++ doesn't want you do it in this case, they are not gone stop you. C++ will allow you to shoot your self in the foot if you really want to. – Caesar Aug 31 '13 at 06:59
  • I suggest you also add an example for that last paragraph so future visitors can see what reinterpret_cast is all about in one glance. – stijn Aug 31 '13 at 07:21
  • @sunlight07 After thinking about it, I edited my answer a little to be more clear. Tell me what you think – Caesar Aug 31 '13 at 15:33
  • I think your answer is really great to explain the logic of "*reinterpret_cast(a)". It seems hard to explain why "reinterpret_cast(a)" isn't allowed and "reinterpret_cast(a)" is allowed in a similar way. – sunlight07 Sep 01 '13 at 10:47
  • But what's the difference from a static cast in this case? If I just do `int b = *((int*)&a);` ? – rustyx Oct 28 '14 at 20:32
  • @rustyx This type of casting is what is called a c-style cast. It will than do a static cast in this case and that will do it is best to maintain the value stored. So if `a = 12.2` than `b` will be equal to `12` – Caesar Oct 30 '14 at 05:35
  • @Caesar Sorry, this is plain wrong. We have only a pointer cast and a dereferencing of that pointer, so no value conversion/truncation or similar will happen. This would happen if had written `int b = (int)a` but not in this case. – Elmar Zander Oct 19 '21 at 06:48
  • 1
    why did you specifically mention `unsigned int` despite the usage of `int` which is signed? – xyf Jul 17 '22 at 01:15
  • Edited to `int`, to match with the code. @xyf mentioned about it, too. Both `int` or `unsigend int` would be fine I think, but any explanation would be helpful if it should be `unsigned int`. – starriet Aug 29 '23 at 13:12
12

You can't reinterpret_cast in the case you give because reinterpret_cast takes only either a int to convert to a pointer, or the reverse, and follows additional similar rules.

There is a summary of these rules there: http://en.cppreference.com/w/cpp/language/reinterpret_cast

Klaim
  • 67,274
  • 36
  • 133
  • 188
4

why cannot cast it directly?

I believe that this is a pure design decision, to make C++ more type-safe than C.

reinterpret_cast is very dangerous, because it can involve type aliasing which is a short way to undefined behavior. When you use C++ casts, you sign a contract with your compiler "I know, what I am doing". So, all these long operators names, angle brackets, type-pointer-type conversions telling you: "Wait, don't do it. Maybe there is something wrong in your code design!".

Also, not all C++ compilers allow type aliasing (either achieved by casting or by unions).

Community
  • 1
  • 1
Ivan Aksamentov - Drop
  • 12,860
  • 3
  • 34
  • 61
3

In the second case, it is not a cast from the value a to b. In fact, that is just a conversion. b will not point to x and pretend that it points to a float. Conversion constructs a new value of type int and assigns it the value from a.

There are several ways to do this conversion correctly in C++.

One is simply to use static cast as usual. This is the recommended solution:

int b = static_cast<int>(a);

You could use reinterpret_cast in the following way below. Note this is doing the reinterpretation for the bit patter, and not conversion unlike the alternatives mentioned:

int b = reinterpret_cast<int&>(a);

You could also use the C style cast:

int b = (int)a;

You could also use the C++ function style casting:

int b = int(a);

You could get the implicit conversation as well, albeit it might generate a warning:

int b = a;

The static cast is recommended in this special case, but at least do not use the implicit conversation, nor the C style in C++.

László Papp
  • 51,870
  • 39
  • 111
  • 135
  • `int(a)` is not a C++ style cast, it's just another way of writing `(int)a`. – David Brown Aug 31 '13 at 06:05
  • 2
    @David: I am afraid, you are wrong unfortunately. Try to compile that with C ... Please consider reverting your -1. It just demotivates me and also others in the future when finding my thorough reply. :( main.c:4:13: error: expected expression before ‘int’ int b = int(a); – László Papp Aug 31 '13 at 06:07
  • @David: I do not like my update because I do think that is usually mentioned as "C++ style cast", but I updated it only for making you happy, and myself a bit less happy. I hope your -1 can now be reverted... – László Papp Aug 31 '13 at 06:10
  • @LaszloPapp: If you worry about reputation this much, the fastest way to earn it is to keep answering questions. Downvote gives -1 rep. Upvote gives either +5 or +10 rep. Thorough reply does not guarantee more reputation, by the way. – SigTerm Aug 31 '13 at 06:14
  • 3
    @LaszloPapp It wasn't me who downvoted, so I can't reverse it. – David Brown Aug 31 '13 at 06:15
  • 1
    @DavidBrown: Assuming my sleepy brain works correctly, int() calls constructor for an int. (int) performs cast/conversion. Not the same thing, although it could yield identical machine code (because int is built-in type). – SigTerm Aug 31 '13 at 06:17
  • @SigTerm: I think you misunderstand, and it is not about the reputation, but that it is misleading the readers later without any evidence why. Again, dear downvoter: could you please let me know how to improve this reply if any? – László Papp Aug 31 '13 at 06:17
  • C++ functional notation casting is odd; attempting to cast to `long long(a)` won't work (btw, I'm not the mysterious down voter, since there seems to be a witch-hunt). – Mr. Smith Aug 31 '13 at 06:18
  • @DavidBrown: The important difference: int() (without arguments) will return 0. (int) is an empty statement and does nothing (and doesn't compile). – SigTerm Aug 31 '13 at 06:20
  • @Mr.Smith: Probably because it can't be recognized as a single identifier. `typedef long long ll; ll a = ll(b);` will work. – SigTerm Aug 31 '13 at 06:21
  • @SigTerm: uh, a can you post an example of where `(T)obj` results in different behavior than `T(obj)` for some `T`? – user541686 Aug 31 '13 at 06:28
  • 1
    @Mehrad: Any object with private constructor and cast operator. – SigTerm Aug 31 '13 at 06:39
  • Would be great, if you would also say which casts reinterpret the bit pattern and which actually do the float->int conversion. – cmaster - reinstate monica Aug 31 '13 at 08:53
  • downvoter, any reason, and suggestion how to improve this post? – László Papp Sep 01 '13 at 17:30
2

With reinterpret_cast you can cast a pointer type to any other pointer type, for example you can cast float pointer to int pointer:

float *a = new int(0);
int* b = reinterpret_cast<int*>(a);
cpp
  • 3,743
  • 3
  • 24
  • 38