Related
I am new to C++ style casts and I am worried that using C++ style casts will ruin the performance of my application because I have a real-time-critical deadline in my interrupt-service-routine.
I heard that some casts will even throw exceptions!
I would like to use the C++ style casts because it would make my code more "robust". However, if there is any performance hit then I will probably not use C++ style casts and will instead spend more time testing the code that uses C-style casts.
Has anyone done any rigorous testing/profiling to compare the performance of C++ style casts to C style casts?
What were your results?
What conclusions did you draw?
If the C++ style cast can be conceptualy replaced by a C-style cast there will be no overhead. If it can't, as in the case of dynamic_cast, for which there is no C equivalent, you have to pay the cost one way or another.
As an example, the following code:
int x;
float f = 123.456;
x = (int) f;
x = static_cast<int>(f);
generates identical code for both casts with VC++ - code is:
00401041 fld dword ptr [ebp-8]
00401044 call __ftol (0040110c)
00401049 mov dword ptr [ebp-4],eax
The only C++ cast that can throw is dynamic_cast when casting to a reference. To avoid this, cast to a pointer, which will return 0 if the cast fails.
The only one with any extra cost at runtime is dynamic_cast, which has capabilities that cannot be reproduced directly with a C style cast anyway. So you have no problem.
The easiest way to reassure yourself of this is to instruct your compiler to generate assembler output, and examine the code it generates. For example, in any sanely implemented compiler, reinterpret_cast will disappear altogether, because it just means "go blindly ahead and pretend the data is of this type".
Why would there be a performance hit? They perform exactly the same functionality as C casts. The only difference is that they catch more errors at compile-time, and they're easier to search for in your source code.
static_cast<float>(3) is exactly equivalent to (float)3, and will generate exactly the same code.
Given a float f = 42.0f
reinterpret_cast<int*>(&f) is exactly equivalent to (int*)&f, and will generate exactly the same code.
And so on. The only cast that differs is dynamic_cast, which, yes, can throw an exception. But that is because it does things that the C-style cast cannot do. So don't use dynamic_cast unless you need its functionality.
It is usually safe to assume that compiler writers are intelligent. Given two different expressions that have the same semantics according to the standard, it is usually safe to assume that they will be implemented identically in the compiler.
Oops: The second example should be reinterpret_cast, not dynamic_cast, of course. Fixed it now.
Ok, just to make it absolutely clear, here is what the C++ standard says:
§5.4.5:
The conversions performed by
a const_cast (5.2.11)
a static_cast (5.2.9)
a static_cast followed by a const_cast
a reinterpret_cast (5.2.10), or
a reinterpret_cast followed by a const_cast.
can be performed using the cast
notation of explicit type conversion.
The same semantic restrictions and
behaviors apply. If a conversion can
be interpreted in more than one of the
ways listed above, the interpretation
that appears first in the list is
used, even if a cast resulting from
that interpretation is ill-formed.
So if anything, since the C-style cast is implemented in terms of the C++ casts, C-style casts should be slower. (of course they aren't, because the compiler generates the same code in any case, but it's more plausible than the C++-style casts being slower.)
There are four C++ style casts:
const_cast
static_cast
reinterpret_cast
dynamic_cast
As already mentioned, the first three are compile-time operations. There is no run-time penalty for using them. They are messages to the compiler that data that has been declared one way needs to be accessed a different way. "I said this was an int*, but let me access it as if it were a char* pointing to sizeof(int) chars" or "I said this data was read-only, and now I need to pass it to a function that won't modify it, but doesn't take the parameter as a const reference."
Aside from data corruption by casting to the wrong type and trouncing over data (always a possibility with C-style casts) the most common run-time problem with these casts is data that actually is declared const may not be castable to non-const. Casting something declared const to non-const and then modifying it is undefined. Undefined means you're not even guaranteed to get a crash.
dynamic_cast is a run-time construct and has to have a run-time cost.
The value of these casts is that they specifically say what you're trying to cast from/to, stick out visually, and can be searched for with brain-dead tools. I would recommend using them over using C-style casts.
When using dynamic_cast several checks are made during runtime to prevent you from doing something stupid (more at the GCC mailing list), the cost of one dynamic_cast depends on how many classes are affected, what classes are affected, etc.
If you're really sure the cast is safe, you can still use reinterpret_cast.
Although I agree with the statement "the only one with any extra cost at runtime is dynamic_cast", keep in mind there may be compiler-specific differences.
I've seen a few bugs filed against my current compiler where the code generation or optimization was slightly different depending on whether you use a C-style vs. C++-style static_cast cast.
So if you're worried, check the disassembly on hotspots. Otherwise just avoid dynamic casts when you don't need them. (If you turn off RTTI, you can't use dynamic_cast anyway.)
The canonical truth is the assembly, so try both and see if you get different logic.
If you get the exact same assembly, there is no difference- there can't be. The only place you really need to stick with the old C casts is in pure C routines and libraries, where it makes no sense to introduce C++ dependence just for type casting.
One thing to be aware of is that casts happen all over the place in a decent sized piece of code. In my entire career I've never searched on "all casts" in a piece of logic- you tend to search for casts to a specific TYPE like 'A', and a search on "(A)" is usually just as efficient as something like "static_cast<A>". Use the newer casts for things like type validation and such, not because they make searches you'll never do anyway easier.
This question already has answers here:
Why does C++ require a cast for malloc() but C doesn't?
(4 answers)
Closed 9 years ago.
According to this
It is preferred to not cast malloc in C because if the return of malloc is cast then the error which would be flagged is hidden, resulting in a difficult to find bug. Also, during maintenance, if the type of the pointer changes but the cast is not changed, once again there is a difficult to find bug. The method most experienced programmers choose is:
p = malloc ( n * sizeof *p );
There is no cast for malloc since there is no need for one, and instead of using sizeof ( type ) to determine the size of the block, sizeof *ptr is used. By dereferencing the pointer and taking its size, the proper value is given without having to worry about modifying the allocation request if the type of the pointer changes.
but it won't compile in C++. why?
and what does it means that if the return of malloc is cast then the error which would be flagged is hidden ?
it won’t compile in C++. why?
Because C and C++ are different languages.
Implicit conversions between void * and other pointer types are allowed by the C standard. They are not allowed by the C++ standard. In C the cast is unnecessary, and fails the basic programming guideline of “don’t repeat yourself”, whereas in C++ the language requires a cast (it’s not a question of preference).
what does it means that if the return of malloc is cast then the error which would be flagged is hidden ?
Implicit function declaration is no longer part of the C language, but many compilers continue to support it as an extension for compatibility with old codebases. If a C function does not have a prototype, it is assumed to return int. If you inadvertently leave #include <stdlib.h> out of your code but call malloc, the compiler may assume that it returns int instead of void *[1]. With an explicit cast, the assumed int result will be converted to a void * which in general may result in an invalid pointer. This is bad, and may result in hard-to-diagnose runtime failures.
If, on the other hand, you do not have an explicit cast, you will get a warning or error at compile time pointing to the exact source of the error, which is much easier to diagnose and fix.[2]
In practice, this is less of an issue with malloc than it is with your own functions that return pointers (or other types), as many compilers know about malloc and handle it specially.
In practice, some modern compilers will actually warn whether or not you have the cast, but there are definitely compilers still in use that will not warn if the cast is present, which leads to justified paranoia and defensive programming.
but it won't compile in C++. why?
It's a trade-off between the convenience of using void* as a generic pointer, and the safety of preventing invalid type conversions.
In C, void* is widely used, as it's the only reasonable way to write generic code; so, in that language, it can be implicitly converted to another pointer type for convenience.
In C++, there are type-safe ways of writing generic code, so void* is rarely used; in particular, you'd use the type-safe new to allocate and initialise an object, rather than malloc to allocate raw memory and pretend it contained an object. So, in that language, implicit conversion from void* is forbidden to give stronger type safety.
and what does it means that if the return of malloc is cast then the error which would be flagged is hidden ?
The clue is in the previous sentence:
There is nothing wrong with this except in the event that stdlib.h, the header which declares malloc, is not included
In (older dialects of) C, you can call a function which hasn't been declared; that implicitly declares a function with a return type of int. So, if you were to call malloc without including the header, you'd get code that erroneously assumed that it returned int. Without a cast, you'd get a compiler error when you tried to assign it to a pointer. With a cast, the code would compile, potentially giving obscure runtime errors and lengthy debugging sessions.
In C++ (and modern C), all functions must be declared before use, so this error couldn't happen even if you did use malloc for some reason.
It's not allowed in C++ language, because C++ has type safety
It has to do with type safety. Specifically C allows implicit casting from void* to other types but c++ doesn't, this is why it compiles in C but not C++. This is one of the ways in which C and C++ are different. C is not a subset of C++.
In c++ you should be using new and not malloc. New does a type safe allocation which gets around this issue.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why do we have reinterpret_cast in C++ when two chained static_cast can do it's job?
I have been suggested that i should not use reinterpret_cast or const_cast in case of pointer to pointer conversion. Only dynamic_cast should be used.Because other cast can create problem in future. So my question is why not reinterpret_cast or other cast which is dangerous has been removed from c++ standard.
Because there are times when you need a cast which does what reinterpret_cast does. As for dynamic_cast, I almost never use this cast; that's only for casting from a parent type to a more derived type. Most of the time I can prove which child type I'm working with, and I use static_cast. I also use static_cast for compile time type conversions, for example from signed to unsigned integers.
static_cast, not dynamic_cast, is the most common kind of cast. If your design relies on dynamic_cast too heavily, that's a code smell indicating your class hierarchy violates LSP in most cases.
In the real world, you frequently have to cast pointers in ways the compiler/runtime can't validate. For example, in pthreads you pass a void* to the new thread's start routine. Sometimes that arg is actually a class? The compiler has no way to tell. It's one of those "real life" issues.
Incidentally I find myself using dynamic_cast infrequently. My main use for is has been exception type scraping in catch blocks.
They are dangerous but sometimes you need them.
C++ is not know for removing constructs that are dangerous to the new user. We will let you run with those scissors (while eating cake).
What makes them good is that the dangerous code sticks out so it is easy to spot. So when people do code reviews they can quickly spot the stuff that is dangerous and add a little scrutiny more checking.
Use reinterpret_cast for casting between unrelated pointer types.
Use static_cast for explicit, supported conversions.
Use dynamic_cast to cast a pointer of one type to a pointer of a derived type.
If you know a pointer to a parent type points to a child type, you can safely static_cast from the parent type to the child type. A cast from a child type pointer to a parent type pointer is implicit and requires no explicit cast.
A reinterpret_cast example from my own code base:
unsigned int CTaskManager::CWorker::WorkerMain(void* Parameters)
{
CWorker* This = reinterpret_cast<CWorker*>(Parameters);
// ...
}
bool CTaskManager::CWorker::Initialize()
{
// ...
// Create worker.
m_ThreadHandle = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, &(WorkerMain), this, 0, NULL));
// ...
}
A lot of dangerous operations, though they should generally be avoided, do have a rare legitimate usage. Furthermore, the rule of thumb when it comes to language features and APIs is that once it's there, you can't get rid of it; removing a feature from the C++ language has the potential to break lots of existing C++ code. Typically removal of features requires demonstration that it is not used or that the use is so limited that the cost impact of getting rid of it would be small. Even trigraphs, which are almost never used (unless you are at IBM) and which people wanted to get rid of survived the axe. These various casts and other usually dangerous operations are used way, way more than trigraphs are.
I have been reading a lot about C++ casting and I am starting to get confused because I have always used C style casting.
I have read that C style casting should be avoided in C++ and that reinterpret_cast is very very dangerous and should not be used whenever there is an alternative. On the contrary to not using reinterpret_cast, I have seen it used many times on MSDN in their sample code. This leads me to ask my first question, when is it ok to use reinterpret_cast?
For example:
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_CREATE:
{
LPCREATESTRUCT lpCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
return 0;
}
}
...
}
If that is not ok, then how would I cast the LPARAM value to a pointer using only static, dynamic, and/or const casting?
Also: If reinterpret_cast is not portable, how would I rewrite it to be portable (for good practice)
Using reinterpret_cast is acceptable if you know that the pointer was originally of the destination type. Any other use is taking advantage of implementation-dependent behavior, although in many cases this is necessary and useful, such as casting a pointer to a structure into a pointer to bytes so that it can be serialized.
It is considered dangerous because it does no checking, either at compile-time or at runtime. If you make a mistake, it can and will crash and burn horribly, and be difficult to debug. You are essentially telling the compiler "I know better than you what this actually is, so just compile the code and let me worry about the consequences."
The reason you see it on MSDN is because the Win32 API is a C API, but people insist on giving examples in C++.
Reinterpret cast is fine when you're writing code that interfaces with other libraries. It should be avoided within your own app.
This is an example of programming the Windows Platform SDK, a C API, with C++. The window procedure only has the WPARAM and LPARAM parameters and if you need to pass a pointer to a structure through a window message, it has to be cast. This is a perfectly acceptable use of reinterpret_cast<> in my opinion. You cannot avoid a cast because the SDK you are writing to, which is not your code, was not designed for C++, much less type-safety, and needs the casting to provide generic parameter types with a C binding.
The reinterpret_cast<> here is a flag that lets you know you need to be careful, but it is not to be avoided at all costs.
If, on the other hand, you controlled both sides of the code, the API and the consumer, it would be better to make an API that was type-safe and did not require the consumer to perform casts to use it correctly.
Not to disrespect MSDN, but MSDN is not the best place to go for proper C++ coding.
One reason to use reinterpret_cast is when you're casting to/from opaque datatypes. reinterpret_cast is not "dangerous" it's just that it's easy to screw up and lead to problems in your code, which is why it should be avoided.
The reason why the C++ style casts are preferred are that, static_cast is typesafe, and all casting times are easier to search for.
Programmers [incorrectly] often use casts to "cast off compiler warnings" such as converting from unsigned to signed integers, or from a 32bit integer to an 8bit one.
Essentially reinterpret_cast is "safe" with C structures and basic types (baring plain mistakes like casting int to a pointer and back, which works on ILP32 architecture but breaks on LP64 one.) A C structure doesn't have anything in it, except possible padding for alignment, that you didn't declare.
reinterpret_cast is not safe with C++ polymorphic types since compiler inserts data items into your class - things like pointers to virtual tables and pointers to virtual base classes. Other C++ casts take care of adjusting these when, say, down-casting from pointer to base class to pointer to derived class, reinterpret_cast and C-style casts don't.
I am new to C++ style casts and I am worried that using C++ style casts will ruin the performance of my application because I have a real-time-critical deadline in my interrupt-service-routine.
I heard that some casts will even throw exceptions!
I would like to use the C++ style casts because it would make my code more "robust". However, if there is any performance hit then I will probably not use C++ style casts and will instead spend more time testing the code that uses C-style casts.
Has anyone done any rigorous testing/profiling to compare the performance of C++ style casts to C style casts?
What were your results?
What conclusions did you draw?
If the C++ style cast can be conceptualy replaced by a C-style cast there will be no overhead. If it can't, as in the case of dynamic_cast, for which there is no C equivalent, you have to pay the cost one way or another.
As an example, the following code:
int x;
float f = 123.456;
x = (int) f;
x = static_cast<int>(f);
generates identical code for both casts with VC++ - code is:
00401041 fld dword ptr [ebp-8]
00401044 call __ftol (0040110c)
00401049 mov dword ptr [ebp-4],eax
The only C++ cast that can throw is dynamic_cast when casting to a reference. To avoid this, cast to a pointer, which will return 0 if the cast fails.
The only one with any extra cost at runtime is dynamic_cast, which has capabilities that cannot be reproduced directly with a C style cast anyway. So you have no problem.
The easiest way to reassure yourself of this is to instruct your compiler to generate assembler output, and examine the code it generates. For example, in any sanely implemented compiler, reinterpret_cast will disappear altogether, because it just means "go blindly ahead and pretend the data is of this type".
Why would there be a performance hit? They perform exactly the same functionality as C casts. The only difference is that they catch more errors at compile-time, and they're easier to search for in your source code.
static_cast<float>(3) is exactly equivalent to (float)3, and will generate exactly the same code.
Given a float f = 42.0f
reinterpret_cast<int*>(&f) is exactly equivalent to (int*)&f, and will generate exactly the same code.
And so on. The only cast that differs is dynamic_cast, which, yes, can throw an exception. But that is because it does things that the C-style cast cannot do. So don't use dynamic_cast unless you need its functionality.
It is usually safe to assume that compiler writers are intelligent. Given two different expressions that have the same semantics according to the standard, it is usually safe to assume that they will be implemented identically in the compiler.
Oops: The second example should be reinterpret_cast, not dynamic_cast, of course. Fixed it now.
Ok, just to make it absolutely clear, here is what the C++ standard says:
§5.4.5:
The conversions performed by
a const_cast (5.2.11)
a static_cast (5.2.9)
a static_cast followed by a const_cast
a reinterpret_cast (5.2.10), or
a reinterpret_cast followed by a const_cast.
can be performed using the cast
notation of explicit type conversion.
The same semantic restrictions and
behaviors apply. If a conversion can
be interpreted in more than one of the
ways listed above, the interpretation
that appears first in the list is
used, even if a cast resulting from
that interpretation is ill-formed.
So if anything, since the C-style cast is implemented in terms of the C++ casts, C-style casts should be slower. (of course they aren't, because the compiler generates the same code in any case, but it's more plausible than the C++-style casts being slower.)
There are four C++ style casts:
const_cast
static_cast
reinterpret_cast
dynamic_cast
As already mentioned, the first three are compile-time operations. There is no run-time penalty for using them. They are messages to the compiler that data that has been declared one way needs to be accessed a different way. "I said this was an int*, but let me access it as if it were a char* pointing to sizeof(int) chars" or "I said this data was read-only, and now I need to pass it to a function that won't modify it, but doesn't take the parameter as a const reference."
Aside from data corruption by casting to the wrong type and trouncing over data (always a possibility with C-style casts) the most common run-time problem with these casts is data that actually is declared const may not be castable to non-const. Casting something declared const to non-const and then modifying it is undefined. Undefined means you're not even guaranteed to get a crash.
dynamic_cast is a run-time construct and has to have a run-time cost.
The value of these casts is that they specifically say what you're trying to cast from/to, stick out visually, and can be searched for with brain-dead tools. I would recommend using them over using C-style casts.
When using dynamic_cast several checks are made during runtime to prevent you from doing something stupid (more at the GCC mailing list), the cost of one dynamic_cast depends on how many classes are affected, what classes are affected, etc.
If you're really sure the cast is safe, you can still use reinterpret_cast.
Although I agree with the statement "the only one with any extra cost at runtime is dynamic_cast", keep in mind there may be compiler-specific differences.
I've seen a few bugs filed against my current compiler where the code generation or optimization was slightly different depending on whether you use a C-style vs. C++-style static_cast cast.
So if you're worried, check the disassembly on hotspots. Otherwise just avoid dynamic casts when you don't need them. (If you turn off RTTI, you can't use dynamic_cast anyway.)
The canonical truth is the assembly, so try both and see if you get different logic.
If you get the exact same assembly, there is no difference- there can't be. The only place you really need to stick with the old C casts is in pure C routines and libraries, where it makes no sense to introduce C++ dependence just for type casting.
One thing to be aware of is that casts happen all over the place in a decent sized piece of code. In my entire career I've never searched on "all casts" in a piece of logic- you tend to search for casts to a specific TYPE like 'A', and a search on "(A)" is usually just as efficient as something like "static_cast<A>". Use the newer casts for things like type validation and such, not because they make searches you'll never do anyway easier.