Regarding numerical types, in my view, casts fall in one of two
categories:
1. Casts that change the value of an object
2. Casts that are actually redundant, but get rid of compiler/lint
warnings
As an example, consider this code:
unsigned int ui;
...
unsigned char uc = (unsigned char)ui;
Here, it is not clear from the code what the developer wanted to
achieve:
1. It is possible that ui exceeds the unsigned char range and the
programmer only wants to look at the lower (e. g. 8) bits. Basically,
he wants to cut off significant bits and hence wants to change the
original value.
2. The developer knows that ui cannot hold values that exceed the
unsigned char range, so assigning ui to uc is safe and doesn't lose
bits (i. e. the original value is preserved). He only casts to shut up
the compiler/Lint.
Would it make sense to introduce cast macros that clearly indicate what
the programmer wants to do, as in:
#define VALUE_CAST(type, e) ( (type)(e) )
#define WARNING_CAST(type, e) ( (type)(e) )
In the code below the purpose of the cast would be self-explanatory:
unsigned char uc = WARNING_CAST(unsigned char, ui);
Maybe WARNING_CAST could be even augmented by an assert checking if the
source object is in the range of the target type.
Any comments? 10 1688
Ralf wrote: Regarding numerical types, in my view, casts fall in one of two categories: 1. Casts that change the value of an object 2. Casts that are actually redundant, but get rid of compiler/lint warnings
couldn't you just get a better compiler?
<snip>
--
Nick Keighley
Ralf wrote: Regarding numerical types, in my view, casts fall in one of two categories: 1. Casts that change the value of an object
These, I'd call bugs... Cast are decidedly not the language
constructs one should use to change the value of an object.
2. Casts that are actually redundant, but get rid of compiler/lint
These may not be redundant at all, e.g. where there's genuine
need to change the type of the object containing the value in
question.
warnings
As an example, consider this code:
unsigned int ui; ... unsigned char uc = (unsigned char)ui;
Here, it is not clear from the code what the developer wanted to achieve: 1. It is possible that ui exceeds the unsigned char range and the programmer only wants to look at the lower (e. g. 8) bits. Basically, he wants to cut off significant bits and hence wants to change the original value.
No, the programmer does not really /want/ to change the value,
rather she's just hoping that the high order bits will all be
zero. It is entirely possible to check for that before casting.
2. The developer knows that ui cannot hold values that exceed the unsigned char range, so assigning ui to uc is safe and doesn't lose bits (i. e. the original value is preserved). He only casts to shut up the compiler/Lint.
He may actually cast because the design requires that the value
from this point on resides in an object of a different type.
Think hardware registers in an embedded design here. Would it make sense to introduce cast macros that clearly indicate what the programmer wants to do, as in:
#define VALUE_CAST(type, e) ( (type)(e) ) #define WARNING_CAST(type, e) ( (type)(e) )
In the code below the purpose of the cast would be self-explanatory:
unsigned char uc = WARNING_CAST(unsigned char, ui);
These are certainly possible, but I don't think they bring much
to the party... Maybe WARNING_CAST could be even augmented by an assert checking if the source object is in the range of the target type. Any comments?
And adding asserts to these would certainly be death by
defensive programming. ;-)
My tuppence, anyway...
Cheers
Vladimir
Nick Keighley wrote: Ralf wrote: Regarding numerical types, in my view, casts fall in one of two categories: 1. Casts that change the value of an object 2. Casts that are actually redundant, but get rid of compiler/lint warnings
couldn't you just get a better compiler?
<snip>
A better programmer would be preferable... ;-)
Cheers
Vladimir
Vladimir S. Oka wrote: Ralf wrote:
Regarding numerical types, in my view, casts fall in one of two categories: 1. Casts that change the value of an object
These, I'd call bugs... Cast are decidedly not the language constructs one should use to change the value of an object.
Not always the case, for example it can be the right thing to do with
the to* functions. Have a look at this thread for a discussion of the
issue http://groups.google.co.uk/group/com...813857161a2020 2. Casts that are actually redundant, but get rid of compiler/lint
These may not be redundant at all, e.g. where there's genuine need to change the type of the object containing the value in question.
True. For the OP, examples include printing a pointer using the %p
format specifier, where you need to convert the pointer to a void*
before passing it to printf. warnings
As an example, consider this code:
unsigned int ui; ... unsigned char uc = (unsigned char)ui;
Here, it is not clear from the code what the developer wanted to achieve: 1. It is possible that ui exceeds the unsigned char range and the programmer only wants to look at the lower (e. g. 8) bits. Basically, he wants to cut off significant bits and hence wants to change the original value.
No, the programmer does not really /want/ to change the value, rather she's just hoping that the high order bits will all be zero. It is entirely possible to check for that before casting.
How do you know what the programmer wants without asking the programmer?
There are legal well defined ways to use casts to change values,
although whether they are the method you or I would choose is another
matter. 2. The developer knows that ui cannot hold values that exceed the unsigned char range, so assigning ui to uc is safe and doesn't lose bits (i. e. the original value is preserved). He only casts to shut up the compiler/Lint.
He may actually cast because the design requires that the value from this point on resides in an object of a different type. Think hardware registers in an embedded design here.
A lot of the time such casts are not required. Would it make sense to introduce cast macros that clearly indicate what the programmer wants to do, as in:
#define VALUE_CAST(type, e) ( (type)(e) ) #define WARNING_CAST(type, e) ( (type)(e) )
In the code below the purpose of the cast would be self-explanatory:
unsigned char uc = WARNING_CAST(unsigned char, ui);
These are certainly possible, but I don't think they bring much to the party...
Agreed. I definitely would not use such macros nor would I want them in
code I had to deal with. If it's not obvious why the cast is there (or
in any other instance where the purpose of the code is not clear) you
should use comments. Maybe WARNING_CAST could be even augmented by an assert checking if the source object is in the range of the target type. Any comments?
And adding asserts to these would certainly be death by defensive programming. ;-)
My tuppence, anyway...
Added to which I would not add casts to code to shut up compiler warnings.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
"Ralf" <ra**@hollyfamily.de> writes: Regarding numerical types, in my view, casts fall in one of two categories: 1. Casts that change the value of an object 2. Casts that are actually redundant, but get rid of compiler/lint warnings
As an example, consider this code:
unsigned int ui; ... unsigned char uc = (unsigned char)ui;
This is precisely equivalent to
unsigned int ui;
...
unsigned char uc = ui;
You could argue that the version with the cast is more explicit. On
the other hand, it has to repeat the target type, and it introduces
possibilities for error. For example, suppose you change the type of
the variable to unsigned short, but forget to change the cast.
*All* casts should be viewed with suspicion. There are a few cases
where they're necessary:
Passing an argument to a function that takes a variable number and
type of parameters. (You should always have a visible prototype
for any function you call; for ordinary functions, this will
impose an implicit conversion.)
Arithmetic conversions within expressions. For example:
int x = ...;
int y = ...;
long product = (long)x * (long)y;
Without the casts, the multiplication will be done in type int,
and the value converted to long afterwards. (Actually only one of
the casts is necessary, but I like the symmetry.) (And yes, I'm
assuming that long is wider than int.)
Pointer conversions in deliberately non-portable code.
Probably other cases I haven't thought of.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
In article <35************@news.flash-gordon.me.uk>,
Flash Gordon <sp**@flash-gordon.me.uk> wrote: How do you know what the programmer wants without asking the programmer? There are legal well defined ways to use casts to change values, although whether they are the method you or I would choose is another matter.
Example: I have a floating point value x which is known to be in the
range 0 <= x < 256. I want an unsigned char c with the value floor (x).
c = (unsigned char) x;
is a completely legal way to do this.
c = x;
is also a completely legal way to do this; however, it looks
suspiciously like a programming error.
/* This assignment is ok, we know that 0 <= x < 256 */
c = x;
is also completely legal, and it looks ok to me and you, but it might
not look ok to my compiler or your compiler.
c = floor (x);
is ok, but inefficient, it still looks like a programming error because
x might be outside the range 0 to 255.
c = (unsigned char) floor (x);
is ok, but inefficient, and what is the point of using floor () if you
cast the result to unsigned char immediately afterwards?
Flash Gordon wrote: Vladimir S. Oka wrote: Ralf wrote:
Regarding numerical types, in my view, casts fall in one of two categories: 1. Casts that change the value of an object These, I'd call bugs... Cast are decidedly not the language constructs one should use to change the value of an object.
Not always the case, for example it can be the right thing to do with the to* functions. Have a look at this thread for a discussion of the issue http://groups.google.co.uk/group/com...813857161a2020
In that thread Richard said:
Richard Heathfield <compla...@eton.powernet.co.uk> wrote: Yes, it takes an int. But if you are going to cast it to anything, cast it to unsigned char. Why? Because if you give it anything that is neither EOF nor representable as an unsigned char, you invoke undefined behaviour. If you plan on passing EOF to toupper(), reconsider your design. Otherwise, cast to unsigned char if there is the slightest doubt that your data may not be representable as unsigned char. Rely on good testing procedures to pick up data errors. Or cut code to improve your validation.
I may not have made it clear in my post, by I was actually
trying to make his last point. Yes, you can use casts that
change the value to prevent UB or other problems, but
preferable route is to check your data explicitely. Basically, he wants to cut off significant bits and hence wants to change the original value.
No, the programmer does not really /want/ to change the value, rather she's just hoping that the high order bits will all be zero. It is entirely possible to check for that before casting.
How do you know what the programmer wants without asking the programmer? There are legal well defined ways to use casts to change values, although whether they are the method you or I would choose is another matter.
You're right, we can't tell, and that's where I think the
problem lies. I'd certainly strongly discourage using casts to
change the value of an object: test, change value without
casting if needed, assign to a different type of object (with
or without explicit cast, depending on the case) would be my
preferable way.
I agree with the rest of what you said, hence the big snip
here...
Cheers
Vladimir
Christian Bau <ch***********@cbau.freeserve.co.uk> writes: In article <35************@news.flash-gordon.me.uk>, Flash Gordon <sp**@flash-gordon.me.uk> wrote:
How do you know what the programmer wants without asking the programmer? There are legal well defined ways to use casts to change values, although whether they are the method you or I would choose is another matter.
Example: I have a floating point value x which is known to be in the range 0 <= x < 256. I want an unsigned char c with the value floor (x).
c = (unsigned char) x;
is a completely legal way to do this.
c = x;
is also a completely legal way to do this; however, it looks suspiciously like a programming error.
/* This assignment is ok, we know that 0 <= x < 256 */ c = x;
is also completely legal, and it looks ok to me and you, but it might not look ok to my compiler or your compiler.
[...]
A compiler might give you a warning about this, since it could invoke
undefined behavior of x is outside the range of unsigned char. But a
compiler could as easily give you a warning about the cast -- or about
that ugly tie you're wearing. Once it issues the warning, it *must*
compile the code correctly.
If you're adding a cast for the sole purpose of inhibiting a compiler
warning, you're probably doing something wrong. The classic example
is casting the result of malloc() rather than adding a
"#include <stdlib.h>". This isn't that bad, of course, but it is
potentially dangerous. Consider what happens if you change the type
of c (to signed char, or unsigned short, or whatever) and forget to
change the cast.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Keith Thompson wrote: If you're adding a cast for the sole purpose of inhibiting a compiler warning, you're probably doing something wrong.
That depends, of course, on the warning. I grant that casts can be
abused, but I see no problem with adding a cast to suppress a warning
that a value may lose precision on assigning an int to a unsigned char,
for example, when I know that the value is within range of the
assignment variable. That was the point of the warning cast mentioned
by the OP, I believe.
I prefer to suppress a warning that I investigated so that subsequent
compiler summaries aren't cluttered with warnings I have already checked.
--
Thad
On 21 Jan 2006 06:25:42 -0800, "Ralf" <ra**@hollyfamily.de> wrote: Regarding numerical types, in my view, casts fall in one of two categories: 1. Casts that change the value of an object 2. Casts that are actually redundant, but get rid of compiler/lint warnings
3. Casts which hide a programmer error.
--
Al Balmer
Sun City, AZ This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Steven T. Hatton |
last post by:
The code shown below is an example from the Coin3D documentation. I believe
the use of the C-style cast is safe under the circumstances, but from what
I've been exposed to (TC++PL(SE)), I would...
|
by: Gaurav |
last post by:
http://www.sys-con.com/story/print.cfm?storyid=45250
Any comments?
Thanks
Gaurav
|
by: Howard |
last post by:
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...
|
by: roberts.noah |
last post by:
Where is it in the standard that C style casts are labeled depricated?
I read that on a lot of websites but I can't find it in the standard.
I have BS ISO/IEC 14882:2003 (2nd ed) as published by...
|
by: charlie |
last post by:
Hi,
I found an article on informit.com that talks about C++ casts
http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=285&rl=1
The strange thing is the author says the following...
|
by: dpbsmith.janissary.2006 |
last post by:
I know C++ mostly from "learning by doing." My main reference is
Stoustrup's book. I was puzzled by something in a colleague's code that
looked like this:
abc=BOOL(def)
I asked him what that...
|
by: Vincent RICHOMME |
last post by:
Is there any reason to use static_cast instead of old C syntax ?
Let's say I declare
GLfloat test = static_cast<GLfloat>(x);
or
GLfloat test = (GLfloat) x;
|
by: jacob navia |
last post by:
Hi
I am still writing my tutorial book about C. Here is the section about
casts. I would be interested in your opinions about this. Some people
have definite views about this subject ("never...
|
by: jacob navia |
last post by:
Continuing the discussion about casts, I would like to know
your opinions about the hairy subject of casts as lvalues, i.e.
This will fail under lcc-win32, but MSVC and gcc will
accept it. I...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
| |