Which cast to use; static_cast or reinterpret_cast?
Asked Answered
S

4

12
int i = 1000;
void *p = &i;

int *x = static_cast<int*>(p);
int *y = reinterpret_cast<int*>(p);

which cast should be used to convert from void* to int* and why?

Start answered 18/12, 2010 at 1:53 Comment(3)
You should probably check out this post: #332530 if you have already.Hartzell
Neither. You shouldn't be using a void * to start with.Arouse
possible duplicate of Should I use static_cast or reinterpret_cast when casting a void* to whateverJessicajessie
M
17

static_cast provided that you know (by design of your program) that the thing pointed to really is an int.

static_cast is designed to reverse any implicit conversion. You converted to void* implicitly, therefore you can (and should) convert back with static_cast if you know that you really are just reversing an earlier conversion.

With that assumption, nothing is being reinterpreted - void is an incomplete type, meaning that it has no values, so at no point are you interpreting either a stored int value "as void" or a stored "void value" as int. void* is just an ugly way of saying, "I don't know the type, but I'm going to pass the pointer on to someone else who does".

reinterpret_cast if you've omitted details that mean you might actually be reading memory using a type other than the type is was written with, and be aware that your code will have limited portability.

By the way, there are not very many good reasons for using a void* pointer in this way in C++. C-style callback interfaces can often be replaced with either a template function (for anything that resembles the standard function qsort) or a virtual interface (for anything that resembles a registered listener). If your C++ code is using some C API then of course you don't have much choice.

Marylnmarylou answered 18/12, 2010 at 2:4 Comment(3)
I'd go with static_cast in my case.Start
The implications of your statement is that you should use reinterpret_cast<> if you don't know that the type was an int or correctly aligned?Theola
@Martin: is that a question or a statement? The implications are that you should use reinterpret_cast if you're reinterpreting, which therefore will be implementation-specific. On some implementations, the alignment requirement for int is 1, so that issue doesn't arise. On another implementation where the pointer could be mis-aligned, the same code would have exceeded its "limited portability". On still another implementation, you can't type-pun at all (except with char) because of strict aliasing rules.Marylnmarylou
F
1

In current C++, you can't use reinterpret_cast like in that code. For a conversion of void* to int* you can only use static_cast (or the equivalent C-style cast).

For a conversion between different function type pointers or between different object type pointers you need to use reinterpret_cast.

In C++0x, reinterpret_cast<int*>(p) will be equivalent to static_cast<int*>(p). It's probably incorporated in one of the next WPs.

It's a misconception that reinterpret_cast<T*>(p) would interpret the bits of p as if they were representing a T*. In that case it will read the value of p using p's type, and that value is then converted to a T*. An actual type-pun that directly reads the bits of p using the representation of type T* only happens when you cast to a reference type, as in reinterpret_cast<T*&>(p).

As far as I know, all current compilers allow to reinterpret_cast from void* and behave equivalent to the corresponding static_cast, even though it is not allowed in current C++03. The amount of code broken when it's rejected will be no fun, so there is no motivation for them to forbid it.

Front answered 18/12, 2010 at 2:14 Comment(14)
-1 for "In current C++, you can't use reinterpret_cast like in that code". The cast is permitted, but presumably you meant to write that the effect is not formally guaranteed by the standard. And it isn't directly guaranteed, it's "unspecified". However, for both static_cast and reinterpret_cast conversion T* -> void* -> T* is guaranteed to yield the original value. And since this must hold for every pointer value, to foil it a perverse compiler would have to document some systematic needless change, like adding 1 when reinterpret_cast from void*, and vice versa. Nobody would buy it.Doble
@Alf the cast is not permitted. 5.2.10/1 says "Conversions that can be performed explicitly using reinterpret_cast are listed below. No other conversion can be performed explicitly using reinterpret_cast.". There is no conversion listed that allows void* -> T* or T* -> void*.Front
@Johannes: First, just that that's wrong: it's §5.2.10/7, combined with alignment info for void*. I don't recall where latter is directly specified, if it is, but it's implied by the rule for static_cast, §5.2.9/10. Secondly, 5.2.10/1 that you cite is in direct contradiction with §9.2/17. It's always amazed me that there's no formal Defect Report, but even if that inconsistency wasn't there, even if 5.2.10/1 was good, §5.2.10/7 + §5.2.9/10 says you're wrong on this. Sorry. Or, grin. :-)Doble
@Alf plase note our conversation in the comments on this answer: #4108407Front
@Alf 5.2.10/7 doesn't allow casting a pointer to void from or to anything. void is not an object type. Why is 5.2.10/1 in contradiction with 9.2/17?Front
@Johannes: hey, you may actually be right formally, since void* is not an "object pointer". All compilers allow it. Going to check DR's...Doble
@Johannes: yes I know, see above. we're talking at the same time here.Doble
@Alf I'm ok with the -1 for my retard pedantry :) I've clarified it a little more at the end tho.Front
@Johannes: re "Why is 5.2.10/1 in contradiction with 9.2/17?", because it says what follows is an exhaustive list. and in this exhaustive list §5.2.10/7 says "result is unspecified". Then §9.2/17 contradicts that by specifying the result in certain cases. You might alternatively say it's §5.2.10/7 that contradicts §9.2/17.Doble
@Johannes: well the clarification at the end gives entirely wrong impression. You might start with "Due to a Defect in the Holy C++98 Standard, it's only in practice that you can use reinterpret_cast as in the code above, until C++0x is adopted". Yes?Doble
@Alf that's not a contradiction. The range of permissable behaviors for "unspecified behavior" is usually delineated by the Standard (paraphrased from the Standard; see its definition). If one paragraph says behavior for X is unspecified, and another paragraph says that when you do Y, which is a special case of X, the result must be Z, then the unspecified behavior is "you may yield all results for X, except when Y is done, in which case the result must be Z."Front
@Alf well, my impression is that it wasn't a defect in C++03. It started to become a defect in C++0x when certain paragraphs in it assumed that reinterpret_cast from void* would be possible :) Using reinterpret_cast<void*>(...) is plain wrong in current C++ - it makes conceptually no sense either because reinterpret_cast is intended to be used to reinterpret something. With "void" one cannot reinterpret anything. Of course., I think my interpretation of this seems to be a bit retarded, though.Front
@Johannes: even Comeau likes 'em reinterpret_casts. what it does is conceptually to "reinterpret" a pointer value, hence the name. doesn't matter what pointer points to.Doble
@Alf comeau has a host of issues with correctly implementing C++03. I've long given up on it. They are all lead by cash, sadly, not by word of truth.Front
T
0

When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used? gives some good details.

Thilda answered 22/5, 2011 at 15:27 Comment(0)
G
-1

From the semantics of your problem, I'd go with reinterpret, because that's what you actually do.

Gwin answered 18/12, 2010 at 1:55 Comment(3)
I disagree, since in this trivial example it is obviously known that the void* p actually points to an integer, only a static_cast is required. The reinterpret cast is more risky, since it would allow some very weird behavior in the future if somebody mucks with the code that assigns void* p.Hartzell
@Paul: surely the static_cast allows the same weird behavior if somebody mucks with the assignment to p, e.g. assigning from a pointer to something smaller than an int. I think the reason to use static_cast is to communicate the intent of the conversion (i.e. that it's not supposed to reinterpret), but the cast itself doesn't actually prevent a reinterpret from happening, because void* can be converted to and from any object pointer type.Marylnmarylou
@Steve, I see, thanks for the clarification. My understanding of this stuff is somewhat hazy, as I only write C++ from time to time, but the basic comment stands re:static_cast being more appropriate.Hartzell

© 2022 - 2024 — McMap. All rights reserved.