tags:

views:

578

answers:

8

In C++, is (int) ch equivalent to int(ch).

If not, what's the difference?

+1  A: 

The first is the C style, while the second is the C++ style.

In C++, use the C++ style.

warren
One could say that the C++ style is in fact static_cast<int>(ch).
Greg Hewgill
true enough... *but*... that's wordier :P
warren
Wordier true. Also much easier to search for when analyzing code for problems.
Steve Fallows
I'm bemused when people say not to use function-casts for builtin types, but are perfectly happy to use 1-arg constructors for user types, even though they're exactly the same thing. Either follow the reasoning to its logical conclusion, or not at all ;-p
Steve Jessop
@onebyone: No, there's still a crucial difference for UDTs: you *know* that a constructor will be called. For elementary data types you can't be sure; you could trigger a `reinterpret_cast` or cast away `const` without intending to. Not nice. That being said, I usually roll with `static_cast`.
Konrad Rudolph
You can only cast away const like this for pointer types: int(ch) creates a temporary, it doesn't allow ch to be accessed as an int. Likewise, T(ch) creates a temporary constructed with ch.
Steve Jessop
+3  A: 

They are the same.

Dima
they *may* be - but they are not guaranteed to be the same based on the standard
warren
@warren, wrong. 5.2.3 clearly says so.
Konrad Rudolph
no, actually 5.2.3 agrees with me; for a single expression it's "equivalent", but not "identical"; and with more complex expressions, it may or may not be the "same"
warren
So are "equivalent" and "the same" equivalent, the same, or identical?
Steve Jessop
+18  A: 

They are the same thing, and also the same as (int)(ch). In C++, it's generally preferred to use a named cast to clarify your intentions:

  • Use static_cast to cast between primitive types of different sizes or signednesses, e.g. static_cast<char>(anInteger).
  • Use dynamic_cast to downcast a base class to a derived class (polymorphic types only), e.g. dynamic_cast<Derived *>(aBasePtr).
  • Use reinterpret_cast to cast between pointers of different types or between a pointer and an integer, e.g. reinterpret_cast<uintptr_t>(somePtr).
  • Use const_cast to remove the const or volatile qualifiers from variables (VERY DANGEROUS), e.g. const_cast<char *>(aConstantPointer).
Adam Rosenfield
reinterpret_cast is VERY DANGEROUS too. You can at least validly dereference a const_cast-ed pointer, if careful, but about the only thing you can validly do with a reinterpret_cast-ed pointer is to later reinterpet_cast it back to the original type. Ooh, I think you can safely compare it...
Steve Jessop
+10  A: 

int(x) is called function-style cast by the standard and is the same as the C-style cast in every regard (for POD) [5.2.3]:

If the expression list is a single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4).

Konrad Rudolph
A: 

If you want to be super-nasty, then if you write something like:

#define int(x) 1

Then (int)x has the meaning you expect, while int(x) will be 1 for any value of x. However, if anyone ever did this, you should probably kill them. I can also quite believe that somewhere in the standard you are forbidden from #defining keywords, although I can't find it right now.

Except for that, very stupid, special case, then as said before, [5.3.2] says they are the same for PODs

Chris Jefferson
+2  A: 

Although the two syntaxes have the same meaning for int, the second, constructor-style syntax is more general because it can be used with other types in templates. That is, "T(x)" can be compiled into a conversion between primitive types (e.g., if T = int) or into a constructor call (if T is a class type). An example from my own experience where this was useful was when I switched from using native types for intermediate results of calculations to arbitrary-precision integers, which are implemented as a class.

Nathan Kitchen
The same behaviour can be achieved using `static_cast`. As Adam has said, clarification of intent is very important with these dangerous operations. No need to resort to the more dangerous function-style cast.
Konrad Rudolph
This is a good clarification. The function-style cast for primitive types and pointers is fully equivalent to the general-purpose cast in C, which is unsafe because you can corrupt pointers or circumvent the protections provided by "const" and "volatile".
Nathan Kitchen
+2  A: 

Konrad Rudolph is right. But consider that

  • (int) x <-- is valid syntax in C and C++
  • (int*) x <-- is valid syntax in C and C++
  • int (x) <-- is valid in C++, but gives a syntax error in C
  • int* (x) <-- gives a syntax error in both C and C++
+1  A: 

It's worth noting that both styles of casting are deprecated in C++, in favor of the longer, more specific casting methods listed in Adam Rosenfield's answer.

Dan Olson