C-style casts for built-in types?

H

Howard

Hi,

I am maintaining a lot of code that is rife with C-style casts. I've
seen a lot of comments that one should not use C-style casts at all. But
I'm wondering what harm there could be in doing so with the built-in types.
For example, if you have a long which needs to be passed to a function as an
unsigned long, or a char* that needs to be passed as an unsigned char*, or
an unsigned int that needs to be passed as a long, isn't it perfectly safe
to use C-style casts just to avoid compilation problems? When we make
release builds, we generally treat warnings as errors, so there's a lot of
casting going on, and it's a lot less typing to say, for example, (given an
unsigned char* aName): (char*)aName than it is to say
static_cast<char*>(aName). One's 12 characters, the other's 25! That's a
lot of extra work, and what for, exactly? What could go wrong with the
C-style cast in simple cases like this? I know reasons for when I'm dealing
with classes, unrelated pointer types, etc., but what about the simple
built-in types...is there *really* any difference?

Thanks,
-Howard
 
V

Victor Bazarov

Howard said:
I am maintaining a lot of code that is rife with C-style casts. I've
seen a lot of comments that one should not use C-style casts at all. But
I'm wondering what harm there could be in doing so with the built-in types.
For example, if you have a long which needs to be passed to a function as an
unsigned long, or a char* that needs to be passed as an unsigned char*, or
an unsigned int that needs to be passed as a long, isn't it perfectly safe
to use C-style casts just to avoid compilation problems? When we make
release builds, we generally treat warnings as errors, so there's a lot of
casting going on, and it's a lot less typing to say, for example, (given an
unsigned char* aName): (char*)aName than it is to say
static_cast<char*>(aName). One's 12 characters, the other's 25! That's a
lot of extra work, and what for, exactly? What could go wrong with the
C-style cast in simple cases like this? I know reasons for when I'm dealing
with classes, unrelated pointer types, etc., but what about the simple
built-in types...is there *really* any difference?

char, unsigned char, signed char, are all the same size and there is
probably no harm in casting one to another. There are, however, some
cases where the result is, well, questionable. What if you have 128
in an unsigned char and try to convert it to a signed char? The latter
cannot represent 128 (usually). What do you have? Implementation-
defined behaviour. IOW, it's not portable because it's may be
different with another compiler. Can you rely on those?

Unsigned int and long _can_ be of the same size. The same problem
exists when converting between those types -- if the unsigned int has
a value that cannot be represented in the long, the behaviour is set
by the implementation and not necessarily the same for all of them.

Now, if you can make sure that all you do is cast between "congenial"
types, then no big deal, use C-style casts. Hell, nobody can tell you
not to use them, it's your system, you're the maintainer, why should
we care? But the whole hoopla about them is based on the premise that
(a) sometimes you can't make sure and (b) it breeds a bad habit.

I'd say, if your primary concern is for wearing out your fingertips
while typing too much, your system is waaaay too simple or its life
span is waaaay too short to talk about.

V
 
J

John Harrison

Howard said:
Hi,

I am maintaining a lot of code that is rife with C-style casts. I've
seen a lot of comments that one should not use C-style casts at all. But
I'm wondering what harm there could be in doing so with the built-in types.
For example, if you have a long which needs to be passed to a function as an
unsigned long, or a char* that needs to be passed as an unsigned char*, or
an unsigned int that needs to be passed as a long, isn't it perfectly safe
to use C-style casts just to avoid compilation problems? When we make
release builds, we generally treat warnings as errors, so there's a lot of
casting going on, and it's a lot less typing to say, for example, (given an
unsigned char* aName): (char*)aName than it is to say
static_cast<char*>(aName). One's 12 characters, the other's 25! That's a
lot of extra work, and what for, exactly? What could go wrong with the
C-style cast in simple cases like this? I know reasons for when I'm dealing
with classes, unrelated pointer types, etc., but what about the simple
built-in types...is there *really* any difference?

I think the main problem arises when you change the types in your program.
When you change types what had been a benign cast can suddenly become
dangerous. With C style casts you get no warning, the cast will happen
anyway. With C++ style casts you get a bit more insurance.

john
 
S

Siemel Naran

Howard said:
I am maintaining a lot of code that is rife with C-style casts. I've
seen a lot of comments that one should not use C-style casts at all. But
I'm wondering what harm there could be in doing so with the built-in types.
For example, if you have a long which needs to be passed to a function as an
unsigned long, or a char* that needs to be passed as an unsigned char*, or
an unsigned int that needs to be passed as a long, isn't it perfectly safe
to use C-style casts just to avoid compilation problems? When we make
release builds, we generally treat warnings as errors, so there's a lot of
casting going on, and it's a lot less typing to say, for example, (given an
unsigned char* aName): (char*)aName than it is to say
static_cast<char*>(aName). One's 12 characters, the other's 25! That's a
lot of extra work, and what for, exactly? What could go wrong with the
C-style cast in simple cases like this? I know reasons for when I'm dealing
with classes, unrelated pointer types, etc., but what about the simple
built-in types...is there *really* any difference?

To me, C style casts are fine for any value types: if you have a long which
needs to be passed to a function as an unsigned long, or an unsigned int
that needs to be passed as a long. The C++ casts are generally only for
pointer and reference types: if you have a char* that needs to be passed as
an unsigned char* for which I'd use reinterpret_cast. Use const_cast to
cast away const or reference or pointer types, or in rare cases to add 2nd
level const. Use static_cast to cast from base to derived class, and
various other tasks. Use reinterpret_cast for the rest. The C++ style
casts stand out well and code reviews, and can be searched for by your IDE
or editor.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

C++ casts 31
Casts 81
Incompatible type casts 8
Casts on lvalues 74
What types are there beyond built-in and compound? 1
C style casts 24
Organization Assignment in C programming 0
Pointer casts for OOP 2

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top