I have a const uint8_t* that I want to convert to a char* for an interface that expects a char*.
The easiest way to do this is with a C-style cast:
const uint8_t* aptr = &some_buffer;
char* bptr = (char*)aptr;
However, our internal style guide (which is based on the Google C++ Style Guide) bans C-style casts.
Another option is this monstrosity, which I find pretty unreadable:
char *cptr = reinterpret_cast<char*>(const_cast<uint8_t*>(aptr));
These other options I tried all failed to compile:
char* dptr = reinterpret_cast<char*>(aptr);
char* eptr = const_cast<char*>(aptr);
char* fptr = static_cast<char*>(aptr);
Is there any way I can perform this cast using a C++-style cast without nesting two separate cast operations?
Is there any way I can perform this cast using a C++-style cast without nesting two separate cast operations?
Not portably, no. There is no single "the type is wrong and the const is also wrong" cast.
Another option is this monstrosity, which I find pretty unreadable:
char *cptr = reinterpret_cast<char*>(const_cast<uint8_t*>(ptr));
Do that.
Both C++ casts and your internal style guide are striving to make this look monstrous.
You can prevent the repetition of these casts by writing your own cast.
template< typename T >
char* awful_monster_cast( const T * ptr )
{
return reinterpret_cast<char*>(const_cast<T*>(ptr));
}
Is there any way I can perform this cast using a C++-style cast without nesting two separate cast operations?
If you want it done in a single line like char* foo = some_cast(source) then no. The only cast that can remove const is const_cast so you need that plus an additional one to convert that now non const pointer into your source type. That leaves you with the monstrosity
char *cptr = reinterpret_cast<char*>(const_cast<uint8_t*>(aptr));
as the single line solution. This is a safety feature and makes it so it is painfully obvious you are removing constness.
Another option is this monstrosity, which I find pretty unreadable:
char *cptr = reinterpret_cast<char*>(const_cast<uint8_t*>(aptr));
You might find it unreadable, but this is the idiomatic way to express this conversion in C++.
Here's what's important:
You are using a C-style API that, for whatever reason, is not itself const-correct, but you want to preserve the const-correctness of your own code, as much as possible, necessitating a cast to remove the cv-qualifications of the type.
The C-style API uses signed data types, whereas your application uses unsigned data types.
In total, those are two conversions that your code needs to make—removing the const-ness, and converting to a signed type. This demands that you make two explicitly expressed conversions, if you want to obey these coding practices. You may not agree with this principle, but your company/coding practices certainly do.
Of course, I don't think anything is stopping you from writing something like this:
char * convert_to_c_data_buffer(uint8_t const* ptr) {
return reinterpret_cast<char*>(const_cast<uint8_t*>(ptr));
}
char* dptr = convert_to_c_data_buffer(aptr);
Is there any way I can perform this cast using a C++-style cast without nesting two separate cast operations?
Certainly. There is no need to nest those cast operations. Instead, you can use two separate expressions:
auto cuint = const_cast<uint8_t*>(aptr);
auto cptr = reinterpret_cast<char*>(cuint);
Related
I have this following code
size_t returnSize(const char* s)
{
string string(s);
return string.size();
};
size_t returnSize(const int& i)
{
return sizeof(i);
};
template<typename T>
vector<char> Serialize(const T& t)
{
T* pt = new T(t);
vector<char> CasttoChar;
for (int i =0 ;i<returnSize(t);i++)
{
CasttoChar.push_back(reinterpret_cast<const char*>(pt)[i]);
}
delete pt;
return CasttoChar;
};
template<typename T>
T DeSerialize(const vector<char> cstr)
{
T* a = (T*)(&cstr[0]);
return *a;
}
int _tmain(int argc, _TCHAR* argv[])
{
int x = 97;
vector<char> c = Serialize(x);
cout << DeSerialize<int>(c) << endl;
string k = "blabla";
vector<char> c3 = Serialize(k.c_str());
cout << DeSerialize<const char*>(c3) << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
//output is
//97
//blabla
Is this line T* a = (T*)(&cstr[0]); safe?
Also, I tried reinterpret_cast<T*>(&cstr[0]); instead of T* a = (T*)(&cstr[0]); but compiler complained about not being able to convert const char* to int*. so why does the C style cast work?
Refer the standard
Why reinterpret_cast fails?
5.2.10 Reinterpret cast [expr.reinterpret.cast]
The reinterpret_cast operator shall not cast away constness (5.2.11).
An expression of integral, enumeration, pointer, or pointer-to-member
type can be explicitly converted to its own type; such a cast yields
the value of its operand.
Should I use C Cast?
No. Using C Cast instead of C++ Cast is always unsafe. You are trying to remove the constness of an Object which is an UB.
Using reinterpret_cast, will actually trap this error and advise you of during compile time of the potential pitfall.
You should actually use const_cast in this situation. Its the only legal way to convert a const object to a non const object
But Why does a C Cast works
Quoting from the accepted answer from the Question When should static_cast, dynamic_cast and reinterpret_cast be used?
A C-style cast is defined as the first of the following which
succeeds:
const_cast
static_cast
static_cast, then const_cast
reinterpret_cast
reinterpret_cast, then const_cast
So fortunately, it tries the const_cast first.
The C-style cast works because it takes many steps in order to make the cast succeed. It uses the first of the following that succeeds:
const_cast
static_cast
static_cast + const_cast
reinterpret_cast
reinterpret_cast + const_cast
In this case, it's doing the most 'powerful' cast, a reinterpret_cast to const int * followed by const_cast to int*.
The reinterpret_cast alone won't compile, because you're casting away const-ness. The const_cast is required to cast to int*. Doing a reinterpret_cast to const int* would be fine, however.
As an aside, what you're doing is generally unsafe, unless you're using a compiler extension to ensure that any user-defined type you're deserializing to isn't padded.
C style casting in c++ is not a good idea precisily because you go past the checks that prevent you from removing a const or changing the type arbitrary. If you want to make the code work as is you first need to const_cast and then reinterpret_cast, but really try to avoid const casting. To avoid the warning using reinterpret_cast simply declare a as const T*.
Stick to C++ casts. The reason the reinterpret_cast didn't work is you were casting away constness, which isn't cool; you have to use a const_cast for that and you just shouldn't. C casts ignore this.
Having said that, what are you trying to achieve here? You have effectively casting to a char array and memcpying without the efficiency that would bring.
Sorry to chime in here, but your code is broken in several ways, and the casting is just one of them. Concerning the casting, as soon as you use the conversion from/to vector on something that is not just a simple int or so but requires a constructor it will fail. In any case, a two-step conversions from char const* to void const* to T const* is unfortunately necessary.
Now, other problems:
Try the whole thing with a zero-size string. This should now fully answer your actual question, too: No, it's not safe.
You are returning a pointer to a char from DeSerialize<char const*>(). This pointer points into memory owned by the given vector, which is passed by value and after returning from that function ceases to exist! It is pure luck that it seems to work.
Even if you managed to somehow return a char const* from the function, think about who owns that memory now. The point is that this owner must also release the memory. Consider using std::string and making the char const* variant not compile using a specialization of your template.
In general, if you mean this code earnest, begin adding unit tests. It might slow you down now but avoids errors while you go, thus saving time overall. Search for "test-driven development".
There is nothing that assures that the string is NUL-terminated.
Don't use new/delete unless you have to, prefer "plain" stack variables. If you do, take care of properly releasing the memory in case of exceptions (from push_back()). Use auto_ptr (C++98) or unique_ptr (C++11) to make sure the memory is released correctly.
I'm not familiar in C++ casting and I want to convert my C style casting to a C++ casting. Here is my code,
typedef unsigned char u8;
u8 sTmp[20] = {0};
//.. code to put string data in sTmp
char* sData;
sData = (char*)&(sTmp[0]);
Here, I want to convert (char*)&(sTmp[0]) to a C++ casting.
Many thanks.
Your cast is unnecessarily complicated. You get the first element of the array and then the address of that element. On expressions, arrays decay into pointers, so you can get the address of the array by its name alone:
sData = (char*)sTmp;
Like #Richard said above, the best way to do the cast on C++ is using reinterpret_cast, like this:
sData = reinterpret_cast<char*>(sTmp);
Finally, sTemp (like I already mentioned) will decay to a pointer on expressions, specifically an unsigned char* (which is the usual way of addressing raw memory), so it is very likely that you don't actually need to cast it to char* at all. (unless you have to print it, which doesn´t seem right anyway)
Just want to know if there is a disadvantage of not using const_cast While passing a char* and simply type-casting it as (char *) or both are basically one and same ?
#include <iostream>
#include<conio.h>
using namespace std;
void print(char * str)
{
cout << str << endl;
}
int main ()
{
const char * c = "sample text";
// print( const_cast<char *> (c) ); // This one is advantageous or the below one
print((char *) (c) ); // Does the above one and this are same?
getch();
return 0;
}
Is there some disadvantage of using print((char *) (c) ); over print( const_cast<char *> (c) ); or basically both are same ?
First of all, your print function should take a const char* parameter instead of just char* since it does not modify it. This eliminates the need for either cast.
As for your question, C++ style casts (i.e. const_cast, dynamic_cast, etc.) are prefered over C-style casts because they express the intent of the cast and they are easy to search for. If I accidentally use an a variable of type int instead of const char*, using const_cast will result in a compile time error. However if I use a C-style cast it will compile successfully but produce some difficult to diagnose memory issues at runtime.
In this context, they are identical (casting from a "const char*" to a "char*"). The advantages of const_cast are:
It will help catch typos (if you accidentally cast a "const wchar_t*" to a "char*", then const_cast will complain.)
It's easier to search for.
It's easier to see.
The C-style cast (char *) is equivalent if used properly. If you mess up the const_cast, the compiler will warn you, if you mess up the C-style cast you just get a bug.
const_cast is more appropriate because it only casts away constness, and otherwise will warn you about other possible mistakes (like converting one pointer type to another etc), and (char *) will just silently interpret anything you give it as char *. So if you can - better use const_cast for better type safety.
Independently on the effect that C cast do in this particular case, C cast and C++ casts are not the same: C++ distinguish between reinterpret, static, dynamic and const cast.
The semantics of these cast are different and not always equally possible.
C cast can be either static or reinterpret cast (where static is not possible). It must be used where such an ambivalence is a requirement (I cannot imagine how and when), it must be avoided where a well defined and expected behavior is needed.
I do not believe that it is possible to completely avoid C-style casts when writing C++. I was surprised to find out that I needed to use a C-style cast to avoid a compiler truncation warning:
short value_a = 0xF00D; // Truncation warning in VS2008
short value_b = static_cast<short>(0xF00D); // Truncation warning in VS2008
short value_c = (short)0xF00D; // No warning!
Are there other scenarios where there is no C++-style substitute for a C-style cast?
In C++, the C-style cast is defined (§5.4) in terms of C++-style casts. So for every cast you can do C-style, there's a matching C++-style cast (almost).
The "almost" is that C-style casts ignore base class accessibility. That is, there is no equivalent C++-style cast for the following:
struct foo {};
struct bar : private foo {};
bar b;
foo* f = (foo*)&b; // only way this can be done in a well-defined manner
So, no it's not strictly-speaking possible to completely ditch C-style casts. But the number of areas where a (combination of) C++-style casts doesn't suffice is few in count.
The above is the "language answer". What you're experiencing has nothing to do with C-style casts versus C++ casts, but just compiler implementation. Warnings are absolutely implementation-specific, and have nothing to do with C++.
So don't make the mistake of using your findings on this particular compiler in this particular situation for concluding things about C++ in general.
You are just trying to obfuscate your code, it is as simple as that. And the compiler is completely correct in telling you so.
If you have a precise idea what the assigned value should be, use that. My guess is that you have some unfounded presumption of short being 16 bit wide and that the sign representation of the target machine is two's complement. If that is so, assign -4083 to your variable. If you just need your variable as a bit vector, use an unsigned type.
As far as C is concerned the standard simply says about conversion from one integer type to another:
Otherwise, the new type is signed and
the value cannot be represented in it;
either the result is
implementation-defined or an
implementation-defined signal is
raised.
I imagine the the point of view of C++ with this respect is not much different. Other answers mention border cases where in C++ you would need a `C'-style cast to overrule all typechecks that C++ gives you. Feeling the need for them is an indication of bad design.
The case that you give as an example is certainly not one for which I would find any valid circumstances.
There are 4 c++ style casts, const_cast, reinterpret_cast, static_cast and dynamic_cast. They work as follows:
// const_cast casts away constness or adds it
const int const_integer = 5;
const_cast<int>(const_integer) = 3;
// static_cast will perform standards defined casts and will
// cast up or down a c++ inheritance hierarchy without checking the result of the cast
struct b {};
struct a : public b {};
struct c {};
double value = static_cast<double>(0.0f);
b* b_value = new b;
a* a_value = static_cast<a*>(b_value);
// dynamic_cast will perform any cast that static_cast will, but will check to see
// if the cast makes sense. If the values are not pointers, this cast can throw
b* value_b = new b;
a* value_a = new a;
b* new_b = dynamic_cast<b*>(value_a); // will return NULL
a* new_a = dynamic_cast<a*>(value_b); // will not return NULL
// reinterpret_cast will change any type to any other type, as long as the constness of the types is the same.
// the behavior of this cast is implementation specific.
double* a = new double;
*a = 0.0f;
int *b = reinterpret_cast<int*>(a);
A c-style cast in c++ simply tries to perform those casts in a specific order until one of them works. That order is as follows:
a const_cast
a static_cast
a static_cast followed by a const_cast
a reinterpret_cast, or
a reinterpret_cast followed by a const_cast.
So, in short, you can do any c-style cast in c++, because a c-style cast in c++ is just some arrangement of c++ style casts. Get it?
Yes, it is completely possible.
I never use C-style casts. I can write hundreds of thousands of lines of code without having to revert to using reinterpret_cast, C++'s closest cousin to the C-style cast. The only times I have to use reinterpret_cast is when doing socket programming -- a fairly narrow domain, in the big picture.
You don't need to use C-style casts, either. In your other post, you said
I could just use a negative value,
short my_value = -4083;
but in my code it is much more understandable to use hexadecimal.
So in this case you didn't have to use the cast. You chose to.
I was surprised to find out that I needed to use a C-style cast to avoid a compiler truncation warning
I see it the other way around: You use a C-style cast to prevent the compiler from warning you, and I see this as a severe disadvantage of the C-style cast.
if you feel you know what you're doing, then shut up the compiler for this one case by using a compiler-specific way. For example, for VC use something like
#pragma warning(push, disable: XXXX)
// code goes here
#pragma warning(pop)
In these cases, you can use reinterpret_cast. It was meant for a replacement of a unchecked C-style cast. The typical note here: this is unchecked cast, and should be avoided when possible by using the other available: const_cast, dynamic_cast, etc.
Can someone explain this to me:
char* a;
unsigned char* b;
b = a;
// error: invalid conversion from ‘char*’ to ‘unsigned char*’
b = static_cast<unsigned char*>(a);
// error: invalid static_cast from type ‘char*’ to type ‘unsigned char*’
b = static_cast<unsigned char*>(static_cast<void*>(a));
// everything is fine
What makes the difference between cast 2 and 3? And are there any pitfalls if the approach from 3 is used for other (more complex) types?
[edit]
As some mentioned bad design, etc...
This simple example comes from an image library which gives me the pointer to the image data as char*. Clearly image intensities are always positive so I need to interpret it as unsigned char data.
static_cast<void*> annihilate the purpose of type checking as you say that now it points on "something you don't know the type of". Then the compiler have to trust you and when you say static_cast<unsigned char*> on your new void* then he'll just try to do his job as you ask explicitely.
You'd better use reinterpret_cast<> if you really must use a cast here (as it's obvioulsy showing a design problem here).
Your third approach works because C++ allows a void pointer to be casted to T* via static_cast (and back again) but is more restrictive with other pointer types for safety reasons. char and unsigned char are two distinct types. This calls for a reinterpret_cast.
C++ tries to be a little bit more restrictive to type casting than C, so it doesn't let you convert chars to unsigned chars using static_cast (note that you will lose sign information). However, the type void* is special, as C++ cannot make any assumption for it, and has to rely on the compiler telling it the exact type (hence the third cast works).
As for your second question, of course there are a lot of pitfals on using void*. Usually, you don't have to use it, as the C++ type system, templates, etc. is rich enough to not to have to rely in that "unknown type". Also, if you really need to use it, you have to be very careful with casts to and from void* controlling that types inserted and obtained are really the same (for example, not pointer to subclasses, etc.)
static_cast between pointers works correct only if one of pointers is void or that's casting between objects of classes, where one class is inherited by another.
The difference between 2 and 3 is that in 3, you're explicitly telling the compiler to stop checking you by casting to void*. If the approach from 3 is used for, pretty much anything that isn't a direct primitive integral type, you will invoke undefined behaviour. You may well invoke undefined behaviour in #3 anyway. If it doesn't cast implicitly, it's almost certainly a bad idea unless you really know what's going on, and if you cast a void* back to something that wasn't it's original type, you will get undefined behaviour.
Casts between pointers require reinterpret_cast, with the exception of void*:
Casts from any pointer to to void* are implicit, so you don't need to explicitly cast:
char* pch;
void* p = pch;
Casts from void* to any other pointer only require a static_cast:
unsigned char* pi = static_cast<unsigned char*>(p);
beware, when you cast to void* you lose any type information.
what you are trying to do is incorrect, and false, and error prone and misleading. that's why the compilator returned a compilation error :-)
a simple example
char* pChar = NULL; // you should always initalize your variable when you declare them
unsigned char* pUnsignedChar = NULL; // you should always initalize your variable when you declare them
char aChar = -128;
pChar = &aChar;
pUnsignedChar = static_cast<unsigned char*>(static_cast<void*>(pChar));
then, though pUnsignedChar == pChar nonethless we have *pUnsignedChar == 255 and *pChar == -128.
i do believe this is bad joke, thus bad code.