Static analysis flagged this code as nullPointerArithmetic:
static_cast<BYTE*>(NULL) + p_row_fields->offsets.back(), // field offset
where NULL is defined as #define NULL 0
and offsets resolves through typedef to std::vector<int>
The line in question is passed as a BYTE* argument to a method call.
My question is - What could be the purpose of this idiom?
Is there any difference between what's shown and the less eclectic direct cast:
static_cast<BYTE*>(p_row_fields->offsets.back())
Null pointer constant converts to any pointer type, resulting in null pointer value of that pointer type. Thus, static_cast<BYTE*>(NULL) yields a null pointer of type BYTE*. This conversion works implicitly as well.
Strictly speaking, the behaviour of the pointer arithmetic on null is undefined by the standard because (or assuming that) there is no array at the null address.
As far as what the behaviour might be in practice assuming the compiler allows this, one might expect it to behave same as :
reinterpret_cast<Byte*>(
static_cast<std::intptr_t>(
p_row_fields->offsets.back()
)
)
While this is not UB, there is still technically no standard guarantee that the resulting address is what was intended.
Is there any difference between what's shown and the less eclectic direct cast:
static_cast<BYTE*>(p_row_fields->offsets.back())
Yes, there is a difference. Of integer expressions, only compile time constant prvalues with value 0 are convertible to pointer types. Values other than 0, and lvalues such as p_row_fields->offsets.back() can not be static-casted to pointers.
As such, the quoted cast is ill-formed.
I have below C++ code snippet which works perfectly fine:
Address = **(uint32_t **)(0x12345678);
I have a LDRA warning at the line mentioned above Use of C type cast. Can anyone please help me in type casting above instruction to C++ style?
Thanks,
Kalyan
That's a reinterpret_cast
Only the following conversions can be done with reinterpret_cast, except when such conversions would cast away constness or volatility.
A value of any integral or enumeration type can be converted to a pointer type. A pointer converted to an integer of sufficient size and back to the same pointer type is guaranteed to have its original value, otherwise the resulting pointer cannot be dereferenced safely (the round-trip conversion in the opposite direction is not guaranteed; the same pointer may have multiple integer representations) The null pointer constant NULL or integer zero is not guaranteed to yield the null pointer value of the target type; static_cast or implicit conversion should be used for this purpose.
So it would be
Address = **reinterpret_cast<uint32_t **>(0x12345678);
I know that reinterpret_cast is primarily used going to or from a char*.
But I was surprised to find that static_cast could do the same with a void*. For example:
auto foo "hello world"s;
auto temp = static_cast<void*>(&foo);
auto bar = static_cast<string*>(temp);
What do we gain from using reinterpret_cast and char* over static_cast and void*? Is it something to do with the strict aliasing problem?
Generally speaking, static_cast will do cast any two types if one of them can be cast to the other implicitly. That includes arithmetic casts, down-casts, up-casts and cast to and from void*.
That is, if this cast is valid:
void foo(A a);
B b;
foo(b);
Then the both static_cast<B>(a) and static_cast<A>(b) will also be valid.
Since any pointer can be cast implicitly to void*, thus your peculiar behavior.
reinterpret_cast do cast by reinterpreting the bit-pattern of the values. That, as you said in the question, is usually done to convert between unrelated pointer types.
Yes, you can convert between unrelated pointer types through void*, by using two static_cast:
B *b;
A *a1 = static_cast<A*>(b); //compiler error
A *a2 = static_cast<A*>(static_cast<void*>(b)); //it works (evil laugh)!
But that is bending the rules. Just use reinterpret_cast if you really need this.
Your question really has 2 parts:
Should I use static_cast or reinterpret_cast to work with a pointer to the underlying bit pattern of an object without concern for the object type?
If I should use reinterpret_cast is a void* or a char* preferable to address this underlying bit pattern?
static_cast: Converts between types using a combination of implicit and user-defined conversions
In 5.2.9[expr.static.cast]13 the standard, in fact, gives the example:
T* p1 = new T;
const T* p2 = static_cast<const T*>(static_cast<void*>(p1));
It leverages the implicit cast:
A prvalue pointer to any (optionally cv-qualified) object type T can be converted to a prvalue pointer to (identically cv-qualified) void. The resulting pointer represents the same location in memory as the original pointer value. If the original pointer is a null pointer value, the result is a null pointer value of the destination type.*
There is however no implicit cast from a pointer of type T to a char*. So the only way to accomplish that cast is with a reinterpret_cast.
reinterpret_cast: Converts between types by reinterpreting the underlying bit pattern
So in answer to part 1 of your question when you cast to a void* or a char* you are looking to work with the underlying bit pattern, reinterpret_cast should be used because it's use denotes to the reader a conversion to/from the underlying bit pattern.
Next let's compare void* to char*. The decision between these two may be a bit more application dependent. If you are going to use a standard library function with your underlying bit pattern just use the type that function accepts:
void* is used in the mem functions provided in the cstring library
read and write use char* as inputs
It's notable that C++ specific libraries prefer char* for pointing to memory.
Holding onto memory as a void* seems to have been preserved for compatibility reasons as pointer out here. So if a cstring library function won't be used on your underlying bit patern, use the C++ specific libraries behavior to answer part 2 of your question: Prefer char* to void*.
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?
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.
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.
When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used? gives some good details.
From the semantics of your problem, I'd go with reinterpret, because that's what you actually do.
Is it safe to cast pointer to int and later back to pointer again?
How about if we know if the pointer is 32 bit long and int is 32 bit long?
long* juggle(long* p) {
static_assert(sizeof(long*) == sizeof(int));
int v = reinterpret_cast<int>(p); // or if sizeof(*)==8 choose long here
do_some_math(v); // prevent compiler from optimizing
return reinterpret_cast<long*>(v);
}
int main() {
long* stuff = new long(42);
long* ffuts = juggle(stuff);
std::cout << "Is this always 42? " << *ffuts << std::endl;
}
Is this covered by the Standard?
No.
For instance, on x86-64, a pointer is 64-bit long, but int is only 32-bit long. Casting a pointer to int and back again makes the upper 32-bit of the pointer value lost.
You may use the intptr_t type in <cstdint> if you want an integer type which is guaranteed to be as long as the pointer. You could safely reinterpret_cast from a pointer to an intptr_t and back.
Yes, if... (or "Yes, but...") and no otherwise.
The standard specifies (3.7.4.3) the following:
A pointer value is a safely-derived pointer [...] if it is the result of a well-defined pointer conversion or reinterpret_cast of a safely-derived pointer value [or] the result of a reinterpret_cast of an integer representation of a safely-derived pointer value
An integer value is an integer representation of a safely-derived pointer [...] if its type is at least as large as std::intptr_t and [...] the result of a reinterpret_cast of a safely-derived pointer value [or]
the result of a valid conversion of an integer representation of a safely-derived pointer value [or] the result of an additive or bitwise operation, one of whose operands is an integer representation of a
safely-derived pointer value
A traceable pointer object is [...] an object of an integral type that is at least as large as std::intptr_t
The standard further states that implementations may be relaxed or may be strict about enforcing safely-derived pointers. Which means it is unspecified whether using or dereferencing a not-safely-derived pointer invokes undefined behavior (that's a funny thing to say!)
Which alltogether means no more and no less than "something different might work anyway, but the only safe thing is as specified above".
Therefore, if you either use std::intptr_t in the first place (the preferrable thing to do!) or if you know that the storage size of whatever integer type you use (say, long) is at least the size of std::intptr_t, then it is allowable and well-defined (i.e. "safe") to cast to your integer type and back. The standard guarantees that.
If that's not the case, the conversion from pointer to integer representation will probably (or at least possibly) lose some information, and the conversion back will not give a valid pointer. Or, it might by accident, but this is not guaranteed.
An interesting anecdote is that the C++ standard does not directly define std::intptr_t at all; it merely says "the same as 7.18 in the C standard".
The C standard, on the other hand, states "designates a signed integer type with the property that any valid
pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer".
Which means, without the rather complicated definitions above (in particular the last bit of the first bullet point), it wouldn't be allowable to convert to/from anything but void*.
Yes and no.
The language specification explicitly states that it is safe (meaning that in the end you will get the original pointer value) as long as the size of the integral type is sufficient to store the [implementation-dependent] integral representation of the pointer.
So, in general case it is not "safe", since in general case int can easily turn out to be too small. In your specific case it though it might be safe, since your int might be sufficiently large to store your pointer.
Normally, when you need to do something like that, you should use the intptr_t/uintptr_t types, which are specifically introduced for that purpose. Unfortunately, intptr_t/uintptr_t are not the part of the current C++ standard (they are standard C99 types), but many implementations provide them nevertheless. You can always define these types yourself, of course.
In general, no; pointers may be larger than int, in which case there's no way to reconstruct the value.
If an integer type is known to be large enough, then you can; according to the Standard (5.2.10/5):
A pointer converted to an integer of sufficient size ... and back to the same pointer type will have its original value
However, in C++03, there's no standard way to tell which integer types are large enough. C++11 and C99 (and hence in practice most C++03 implementations), and also Boost.Integer, define intptr_t and uintptr_t for this purpose. Or you could define your own type and assert (preferably at compile time) that it's large enough; or, if you don't have some special reason for it to be an integer type, use void*.
Is it safe? Not really.
In most circumstances, will it work? Yes
Certainly if an int is too small to hold the full pointer value and truncates, you won't get your original pointer back (hopefully your compiler will warn you about this case, with GCC truncating conversions from pointer to integers are hard errors). A long, or uintptr_t if your library supports it, may be better choices.
Even if your integer type and pointer types are the same size, it will not necessarily work depending on your application runtime. In particular, if you're using a garbage collector in your program it might easily decide that the pointer is no longer outstanding, and when you later cast your integer back to a pointer and try to dereference it, you'll find out the object was already reaped.
Absolutely not. Doing some makes a bad assumption that the size of an int and a pointer are the same. This is almost always no the case on 64 bit platforms. If they are not the same a precision loss will occur and the final pointer value will be incorrect.
MyType* pValue = ...
int stored = (int)pValue; // Just lost the upper 4 bytes on a 64 bit platform
pValue = (MyType*)stored; // pValue is now invalid
pValue->SomeOp(); // Kaboom
No, it is not (always) safe (thus not safe in general). And it is covered by the standard.
ISO C++ 2003, 5.2.10:
A pointer can be explicitly converted to any integral type large enough to hold it. The mapping function is implementation-defined.
A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined.
(The above emphases are mine.)
Therefore, if you know that the sizes are compatible, then the conversion is safe.
#include <iostream>
// C++03 static_assert.
#define ASSURE(cond) typedef int ASSURE[(cond) ? 1 : -1]
// Assure that the sizes are compatible.
ASSURE(sizeof (int) >= sizeof (char*));
int main() {
char c = 'A';
char *p = &c;
// If this program compiles, it is well formed.
int i = reinterpret_cast<int>(p);
p = reinterpret_cast<char*>(i);
std::cout << *p << std::endl;
}
Use uintptr_t from "stdint.h" or from "boost/stdint.h". It is guaranteed to have enough storage for a pointer.
No it is not. Even if we rule out the architecture issue, size of a pointer and an integer have differences. A pointer can be of three types in C++ : near, far, and huge. They have different sizes. And if we talk about an integer its normally of 16 or 32 bit. So casting integer into pointers and vice-verse is not safe. Utmost care has to be taken, as there very much chances of precision loss. In most of the cases an integer will be short of space to store a pointer, resulting in loss of value.
If your going to be doing any system portable casting, you need to use something like Microsofts INT_PTR/UINT_PTR, the safety after that relies on the target platforms and what you intend doing to the INT_PTR. generally for most arithmatic char* or uint_8* works better while being typesafe(ish)
To an int ? not always if you are on a 64 bit machine then int is only 4 bytes, however pointers are 8 bytes long and thus you would end up with a different pointer when you cast it back from int.
There are however ways to get around this. You can simply use an 8 byte long data type ,which would work whether or not you are on 32/64 bit system, such as unsigned long long unsigned because you don't want sign extension on 32-bit systems.
It is important to note that on Linux unsigned long will always be pointer size* so if you are targeting Linux systems you could just use that.
*According to cppreference and also tested it myself but not on all Linux and Linux like systems
If the issue is that you want to do normal math on it, probably the safest thing to do would be to cast it to a pointer to char (or better yet, * uint8_t), do your math, and then cast it back.