When are unnecessary casts useful?

J

jacob navia

In one of the previous discussions I received a note from
C.B. Falconer indicating me that a cast from long long
to int was unnecessary since the compiler will do that
without the cast automatically.

This is true, but:

Suppose

long long b;
char a;

a = b;

In this assignment, the long long is truncated to a byte. You do
not need a cast in principle to do this, but you are discarding
data when you do this assignment.

I have recently added a warning to the lcc-win32 compiler system
when an assignment like this happens, to warn you about
the implicit data discarding.

To avoid the warning you have to explicitely cast the LHS to meet
the RHS, like this:

a = (char)b;

The cast makes your intentions clear.

The same approach exists in Microsoft compilers.

I have gotten used to do this, more or less automatically when I
cast "down", i.e. from a bigger to a smaller type.

jacob
 
R

Richard Heathfield

jacob navia said:
In one of the previous discussions I received a note from
C.B. Falconer indicating me that a cast from long long
to int was unnecessary since the compiler will do that
without the cast automatically.

This is true, but:

Suppose

long long b;
char a;

a = b;

In this assignment, the long long is truncated to a byte.

Not necessarily. On systems where char is signed and sizeof(long long) is 1,
no information will be lost. But in general, yes, that's correct.

You do
not need a cast in principle to do this, but you are discarding
data when you do this assignment.

If you *are* discarding data, then you're attempting to assign to the char a
value that it cannot hold. On systems where char is unsigned by default,
that's not harmful. On systems where char is signed by default, however,
it's an overflow, and the behaviour is undefined, so the warning is a
useful one.

Whether a cast is beneficial in this situation seems to be a matter of some
dispute. Personally, I think it's unwise to use a cast to suppress a
compiler's diagnostic messages, but - without going so far as to /share/
the opposing view - I can at least see the merit therein, in cases such as
this one.

<snip>
 
J

Jack Klein

In one of the previous discussions I received a note from
C.B. Falconer indicating me that a cast from long long
to int was unnecessary since the compiler will do that
without the cast automatically.

This is true, but:

Suppose

long long b;
char a;

a = b;

In this assignment, the long long is truncated to a byte. You do
not need a cast in principle to do this, but you are discarding
data when you do this assignment.

I have recently added a warning to the lcc-win32 compiler system
when an assignment like this happens, to warn you about
the implicit data discarding.

To avoid the warning you have to explicitely cast the LHS to meet
the RHS, like this:

a = (char)b;

The cast makes your intentions clear.

The same approach exists in Microsoft compilers.

I have gotten used to do this, more or less automatically when I
cast "down", i.e. from a bigger to a smaller type.

I have absolutely no problem with this as long as there is a way to
DISABLE the warning.

There are times when there is a good reason to do non-portable things.
Most of my programming, for example, is in embedded systems with
either real time performance requirements, memory limitation issues,
or both.

A compiler could, and perhaps should, use a high warning level by
default, instead of a low warning level as most do. But there should
be a way to disable diagnostics for legal code that might have
implementation-defined or undefined behavior based on values at run
time.

This is not just a personal preference, it is about the fact that too
many spurious warnings increase the "noise level" and can cause
serious diagnostics to be overlooked.
 
J

Jack Klein

jacob navia said:


Not necessarily. On systems where char is signed and sizeof(long long) is 1,
no information will be lost. But in general, yes, that's correct.



If you *are* discarding data, then you're attempting to assign to the char a
value that it cannot hold. On systems where char is unsigned by default,
that's not harmful. On systems where char is signed by default, however,
it's an overflow, and the behaviour is undefined, so the warning is a
useful one.

Of course you mean, the result is implementation-defined or (on some
nonexistent platforms) an implementation-defined signal is raised.
 
R

Richard Heathfield

Jack Klein said:

Of course you mean, the result is implementation-defined or (on some
nonexistent platforms) an implementation-defined signal is raised.

Oops, you're right - an automatic conversion is indeed required. I take back
the overflow thing.
 
D

David T. Ashley

jacob navia said:
To avoid the warning you have to explicitely cast the LHS to meet
the RHS, like this:

a = (char)b;

The cast makes your intentions clear.

The same approach exists in Microsoft compilers.

I have gotten used to do this, more or less automatically when I
cast "down", i.e. from a bigger to a smaller type.

This comes down to one of the oldest arguments with programming, especially
with 'C'. You should look at Les Hatton's classic work, "Safer C".

Even in areas of the language that are well-defined (i.e. the compiler won't
make mistakes); statistically, humans make mistakes.

You might find in a lot of corporate coding standards the requirement that
if() conditions, be fully parenthesized, i.e.

if ((!a) || (*a > 10))

An experienced programmer will argue this requirement is rubbish (i.e. any
programmer should know precedence and order of evaluation), whereas
management would argue either that (a)it is an area where people are prone
to make mistakes and/or (b)it becomes relevant when there is a team at a
mixed skill level.

This thread and all its derivatives is older than time. (Or, at least it
dates back to nearly 1972.)
 
R

Roland Pibinger

long long b;
char a; ....
a = (char)b;

The cast makes your intentions clear.

BTW, is it legal in C to write:

a = char(b);

It would make the intentions even clearer.

Best regards,
Roland Pibinger
 
R

Richard Heathfield

Roland Pibinger said:
BTW, is it legal in C to write:

a = char(b);

Yes, if you wrap it up in a comment or a string literal.

/* a = char(b); */ is legal, as is "a = char(b);"
It would make the intentions even clearer.

Why?
 
M

Malcolm McLean

jacob navia said:
In one of the previous discussions I received a note from
C.B. Falconer indicating me that a cast from long long
to int was unnecessary since the compiler will do that
without the cast automatically.

This is true, but:

Suppose

long long b;
char a;

a = b;

In this assignment, the long long is truncated to a byte. You do
not need a cast in principle to do this, but you are discarding
data when you do this assignment.
OK, what does it mean to turn a long long integer into a character?
Sometimes, in really low level gubbins code, you might have to do it.
Elsewhere, it should be so rare that it deserves its own function.

Join my campaign for 64 bit ints. Then casting issues shall be magiced away.
 
I

Ian Collins

Malcolm said:
OK, what does it mean to turn a long long integer into a character?
Sometimes, in really low level gubbins code, you might have to do it.
Elsewhere, it should be so rare that it deserves its own function.
Or make the intent clear with something like

a = b&0xff;
Join my campaign for 64 bit ints. Then casting issues shall be magiced away.
Does that include 64 bit char?
 
P

Peter Nilsson

Richard said:
jacob navia said:

Not necessarily. On systems where char is signed and sizeof(long long) is 1,
no information will be lost.

It can still be lost if CHAR_MAX < LLONG_MAX on said implementation.
Though it would be a particularly evil implementation.
 
P

Peter Nilsson

Your subject is generic, but your post is quite particular.

jacob said:
In one of the previous discussions I received a note from
C.B. Falconer indicating me that a cast from long long
to int was unnecessary since the compiler will do that
without the cast automatically.

This is true, but:

Suppose

long long b;
char a;

a = b;

In this assignment, the long long is truncated to a byte. You do
not need a cast in principle to do this, but you are discarding
data when you do this assignment.

Depends what was in b to begin with.
I have recently added a warning to the lcc-win32 compiler system
when an assignment like this happens, to warn you about
the implicit data discarding.

Does lcc-win32 warn you when the pizza's getting cold? That one might
actually be useful. ;-)
To avoid the warning you have to explicitely cast the LHS to meet
the RHS, like this:

a = (char)b;

MUCH better would be if the warning can be disabled from a compiler
option. Your thinking all but forces impressionable newbies to change
their programming style (probably for the worse), and experienced hands
to get cheesed off at unnecessary warnings.
The cast makes your intentions clear.

And what if the type of b changes to a wider type? Whoever maintains
the
code will have to sift through the source looking for spurious casts.
The same approach exists in Microsoft compilers.

Figures.

<snip>
 
Y

Yevgen Muntyan

Peter said:
Your subject is generic, but your post is quite particular.

jacob navia wrote:
[snip]
I have recently added a warning to the lcc-win32 compiler system
when an assignment like this happens, to warn you about
the implicit data discarding.


Does lcc-win32 warn you when the pizza's getting cold? That one might
actually be useful. ;-)

To avoid the warning you have to explicitely cast the LHS to meet
the RHS, like this:

a = (char)b;


MUCH better would be if the warning can be disabled from a compiler
option. Your thinking all but forces impressionable newbies to change
their programming style (probably for the worse), and experienced hands
to get cheesed off at unnecessary warnings.

The cast makes your intentions clear.


And what if the type of b changes to a wider type? Whoever maintains
the
code will have to sift through the source looking for spurious casts.

The same approach exists in Microsoft compilers.


Figures.

GCC and Intel compiler have this thing too, it's not like some
evil microsoft invention picked up by Jacob Navia. You don't want
it you don't use it.

Regards,
Yevgen
 
C

CBFalconer

Peter said:
jacob navia wrote:
.... snip ...


MUCH better would be if the warning can be disabled from a compiler
option. Your thinking all but forces impressionable newbies to change
their programming style (probably for the worse), and experienced
hands to get cheesed off at unnecessary warnings.

Better, from the point of view of training newbies, and from the
point of view of simplicity, is to trigger a warning for ANY cast:

"Warning - possibly erroneous cast encountered".
 
A

ais523

David said:
You might find in a lot of corporate coding standards the requirement that
if() conditions, be fully parenthesized, i.e.

if ((!a) || (*a > 10))

You might find that the extra parentheses have an effect on some
compilers. For instance, if there's an assignment used as the if
condition:

%cat -n test.c
1 int main(void)
2 {
3 char c='c';
4 char* a;
5 a=&c;
6 if(!a || *a > 10) c++;
7 if((!a) || (*a > 10)) c++;
8 if(*a = 10) c++;
9 if((*a = 10)) c++;
10 return 0;
11 }
%gcc -W -Wall test.c
test.c: In function `main':
test.c:8: warning: suggest parentheses around assignment used as truth
value

Note that my version of gcc hasn't warned on line 9; it takes the extra
parentheses as an instruction to suppress the warning. So excess
parenthesisation of this sort can have an effect on compiler
diagnostics, even if it doesn't affect the behaviour of the code.
 
R

Roland Pibinger

Roland Pibinger said:

Yes, if you wrap it up in a comment or a string literal.

/* a = char(b); */ is legal, as is "a = char(b);"


Why?

Well, I guess I'm too much influenced by C++ in that case.
 
R

Richard Bos

BTW, is it legal in C to write:

a = char(b);

It would make the intentions even clearer.

You mean you find calling the char function with an argument of b a
clearer way of expressing "cast the value of b to char" than using a
char-typed cast operator on b? Interesting...

Richard
 
S

Steffen Buehler

Richard said:
You mean you find calling the char function with an argument of b a
clearer way of expressing "cast the value of b to char" than using a
char-typed cast operator on b? Interesting...

Interesting or not, I prefer the latter expression, too. Functions look
more elegant to me than ugly cast operators. What's more,

a = char(b+c*c-d);

saves some keystrokes compared to

a = (char)(b+c*c-d);

Regards
Steffen
 
M

matevzb

more elegant to me than ugly cast operators. What's more,

a = char(b+c*c-d);
This isn't C, it's a C++ constructor if I'm not mistaken. It has a
different meaning than a cast, it is however nevertheless ugly. Almost
as ugly as the abuse ("overloading") of the shift operator.
saves some keystrokes compared to

a = (char)(b+c*c-d);
If I had a penny for each bug I found due to someone "saving some
keystrokes"...
 

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


Members online

Forum statistics

Threads
473,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top