Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > double casts

Reply
Thread Tools

double casts

 
 
Sheldon Simms
Guest
Posts: n/a
 
      11-03-2003
On Mon, 03 Nov 2003 23:56:49 +1100, Peter Nilsson wrote:

> "Sheldon Simms" <(E-Mail Removed)> wrote in message
> news(E-Mail Removed)...
>> On Sun, 02 Nov 2003 18:05:24 -0800, Peter Nilsson wrote:
>> > Sheldon Simms <(E-Mail Removed)> wrote in message

> news:<(E-Mail Removed)>...
>> > ...
>> >> unsigned char uc = 255;
>> >> signed char sc = (signed char)uc;
>> >> /* sc has value -1 */
>> >
>> > There is no standard guarantee that sc has the value -1.
>> >
>> > If 255 <= SCHAR_MAX, then sc gets the value 255, otherwise 255 is
>> > converted in an implementation defined way. [C99 allows an
>> > implementation defined signal to be raised, although that's highly
>> > unlikely.]

>>
>> Thanks for pointing that out, even though I had already said that
>> my code relied on implementation defined behavior.
>>
>> Since you didn't bother quoting it, here's what I said:

>
> It's not that I didn't bother; I wanted to isolate the specific code that my
> comment referred to.
>
>> >> I have some code that uses a few double casts, but they rely on
>> >> implementation-defined behavior

>
> Continued by...
>
>> >> --specifically that an unsigned
>> >> integer cast to a signed integer becomes the signed integer value
>> >> with the same bit value as the unsigned integer.

>
> Which isn't actually enough to give sc the value -1, even on an 8 bit char
> implementation. You need the further assumption of two's complement.


True. I realized after posting that this sentence didn't completely
describe the kind of implementation-defined behavior I was relying on.


 
Reply With Quote
 
 
 
 
Dan Pop
Guest
Posts: n/a
 
      11-03-2003
In <(E-Mail Removed)> Keith Thompson <(E-Mail Removed)> writes:

>Ok, that's a good example of when a double cast is harmful. Are there
>any cases where it's helpful -- i.e., where (A)(B)something differs
>from (A)something *and* (A)(B)something does something useful that
>(A)something does not. In other words, if I see (A)(B)something in
>source code, can I always delete the "(B)" without breaking anything?
>
>Here's one example (assume 8-bit char):
>
> unsigned int n = 257;
> float f0 = (float)n; /* f0 == 257.0 */
> float f1 = (float)(unsigned char)n; /* f1 == 1.0 */
>
>Are there any examples not involving deliberate loss of information?


Sure:

int n = -1;
double f0 = (double)n; /* f0 == -1.0 */
double f1 = (double)(unsigned)n; /* f1 == (double)UINT_MAX */

No information is lost. The value of n can be retrieved from the value
of f1. That is, assuming that a double's mantissa has more bits than an
unsigned.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
 
 
 
Martijn
Guest
Posts: n/a
 
      11-04-2003
> #define ComboBox_LimitText(hwndCtl,cchLimit) \
>
>

((int)(DWORD)SendMessage((hwndCtl),CB_LIMITTEXT,(W PARAM)(int)(cchLimit),0))
>
> Why is this? Does this help in typechecking? (I would think not).
>
> Thanks for the info,


Thanks for everybody who gave this a thought. I guess I'll post it on one
of the MS group, see if any ex-microsoftie has anything to say about it

--
Martijn
http://www.sereneconcepts.nl


 
Reply With Quote
 
Mantorok Redgormor
Guest
Posts: n/a
 
      11-05-2003
Joona I Palaste <(E-Mail Removed)> wrote in message news:<bo3kf6$6v9$(E-Mail Removed)>...
> xarax <(E-Mail Removed)> scribbled the following:
> > "Jack Klein" <(E-Mail Removed)> wrote in message
> > news(E-Mail Removed)...
> >> On Sun, 2 Nov 2003 13:33:05 +0100, "Martijn"
> >> <(E-Mail Removed)> wrote in comp.lang.c:
> >> > Hi,
> >> >
> >> > Those familiar with Windows programming may be familiar with the windowsx.h
> >> > header. In this header macros exist that use double casts, like so (hope
> >> > this is readable):
> >>
> >> Your text is readable, the concept of what the code is doing is not.
> >>
> >> > #define ComboBox_LimitText(hwndCtl,cchLimit) \
> >> >
> >> > ((int)(DWORD)SendMessage((hwndCtl),CB_LIMITTEXT,(W PARAM)(int)(cchLimit),0))
> >> >
> >> > Why is this? Does this help in typechecking? (I would think not).
> >>
> >> Casts never help in type checking, they specifically exist to defeat
> >> type checking.
> >>
> >> > Thanks for the info,
> >>
> >> For a variety of reasons, Windows header files are a complete and
> >> total mess. If you really want to delve into the details, I'd suggest
> >> a Windows programming group or one of Microsoft's support groups.

>
> > That wasn't his question.

>
> > His question is this: When is it necessary, if ever, to use
> > a double cast?

>
> > For example:

>
> > 1. (WPARM)(int)(cchLimit)

>
> > 2. (WPARM)(cchLimit)

>
> > Are these two expressions *always* equivalent? Is there ever
> > a situation where the intermediate cast (int) is necessary
> > to get a "correct" final cast to (WPARM)?

>
> > Just ignore whatever "WPARM" is supposed to be and think
> > about the generic question of double casting versus single casting.
> > Don't get distracted about Windows. This is really a C question.

>
> > For you C gurus out there, what is the definitive answer?

>
> I am not a C guru and cannot answer the OP's question, but I can say
> for certain that in general, an expression of the type (A)(B)something
> is not the same thing as (A)something.
> Proof:
> int i;
> int *p1 = (int *)&i;
> int *p2 = (int *)(long)&i;
> p1 is guaranteed to store i's address. p2 is not.


why would the long mess this up? if i's address can be represented as
long, then wouldn't that be perfectly okay?

- nethlek
 
Reply With Quote
 
Joona I Palaste
Guest
Posts: n/a
 
      11-05-2003
Mantorok Redgormor <(E-Mail Removed)> scribbled the following:
> Joona I Palaste <(E-Mail Removed)> wrote in message news:<bo3kf6$6v9$(E-Mail Removed)>...
>> I am not a C guru and cannot answer the OP's question, but I can say
>> for certain that in general, an expression of the type (A)(B)something
>> is not the same thing as (A)something.
>> Proof:
>> int i;
>> int *p1 = (int *)&i;
>> int *p2 = (int *)(long)&i;
>> p1 is guaranteed to store i's address. p2 is not.


> why would the long mess this up? if i's address can be represented as
> long, then wouldn't that be perfectly okay?


IF i's address can be represented as long. That's a mighty big IF you
got there.
And even if that's true, there's no guarantee the host CPU returns
scalars and pointers in the same way. It could use different registers,
for instance, in which case p2 will be pure garbage.

--
/-- Joona Palaste ((E-Mail Removed)) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"'I' is the most beautiful word in the world."
- John Nordberg
 
Reply With Quote
 
Dan Pop
Guest
Posts: n/a
 
      11-05-2003
In <boalcr$eg7$(E-Mail Removed)> Joona I Palaste <(E-Mail Removed)> writes:

>Mantorok Redgormor <(E-Mail Removed)> scribbled the following:
>> Joona I Palaste <(E-Mail Removed)> wrote in message news:<bo3kf6$6v9$(E-Mail Removed)>...
>>> I am not a C guru and cannot answer the OP's question, but I can say
>>> for certain that in general, an expression of the type (A)(B)something
>>> is not the same thing as (A)something.
>>> Proof:
>>> int i;
>>> int *p1 = (int *)&i;
>>> int *p2 = (int *)(long)&i;
>>> p1 is guaranteed to store i's address. p2 is not.

>
>> why would the long mess this up? if i's address can be represented as
>> long, then wouldn't that be perfectly okay?

>
>IF i's address can be represented as long. That's a mighty big IF you
>got there.


And even then, there is no guarantee that the conversion between pointers
and integers (and vice versa) yields meaningful results. Only C99
provides such a guarantee, *if* intptr_t and uintptr_t are defined (and
used in the conversion) and if the pointers are void pointers. In such
a case, the code would be:

int *p2 = (void *)(intptr_t)(void *)&i;

which is kinda silly, of course. A final cast to int * is not necessary.

>And even if that's true, there's no guarantee the host CPU returns
>scalars and pointers in the same way. It could use different registers,
>for instance, in which case p2 will be pure garbage.


Huh? I can see no function call in the code. What am I missing?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: (E-Mail Removed)
 
Reply With Quote
 
Joona I Palaste
Guest
Posts: n/a
 
      11-05-2003
Dan Pop <(E-Mail Removed)> scribbled the following:
> In <boalcr$eg7$(E-Mail Removed)> Joona I Palaste <(E-Mail Removed)> writes:
>>And even if that's true, there's no guarantee the host CPU returns
>>scalars and pointers in the same way. It could use different registers,
>>for instance, in which case p2 will be pure garbage.


> Huh? I can see no function call in the code. What am I missing?


You're missing the fact that I can sometimes fumble up in my
terminology. By "return" I meant something like "store". Is a cast to
an (int *) allowed to read from a different register than a cast to a
(long)?

--
/-- Joona Palaste ((E-Mail Removed)) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"Ice cream sales somehow cause drownings: both happen in summer."
- Antti Voipio & Arto Wikla
 
Reply With Quote
 
Dan Pop
Guest
Posts: n/a
 
      11-05-2003
In <bob3ic$nb4$(E-Mail Removed)> Joona I Palaste <(E-Mail Removed)> writes:

>Dan Pop <(E-Mail Removed)> scribbled the following:
>> In <boalcr$eg7$(E-Mail Removed)> Joona I Palaste <(E-Mail Removed)> writes:
>>>And even if that's true, there's no guarantee the host CPU returns
>>>scalars and pointers in the same way. It could use different registers,
>>>for instance, in which case p2 will be pure garbage.

>
>> Huh? I can see no function call in the code. What am I missing?

>
>You're missing the fact that I can sometimes fumble up in my
>terminology. By "return" I meant something like "store". Is a cast to
>an (int *) allowed to read from a different register than a cast to a
>(long)?


Now, you're severely confused: the evaluation of an expression is defined
in terms of values, it is immaterial where these values are stored, as
long as all of them are obtained via legit means. It is compiler's job
to do the right thing and it has all the necessary information for that.

Such things can happen only when misdeclared functions are involved.
Consider the following *complete* program (on a C89 implementation):

int main()
{
return sin(0.0);
}

In the absence of an explicit declaration, sin() is implicitly declared
as returning int. Therefore, after generating the function call, the
compiler will expect the return value to be in whatever place a function
returning int will put its return value. But the sin() function doesn't
"know" that and it will put its return value in whatever place a function
returning double is supposed to put its return value. The final result
being that return will use an indeterminate value (but undefined behaviour
has already been invoked by the time sin() was called.

Even worse things can happen if the stack is used for passing back the
return value, because the caller generates a certain stack layout, while
the callee expects another, possibly corrupting stack data containing the
callers local variables or its return address.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: (E-Mail Removed)
 
Reply With Quote
 
Joona I Palaste
Guest
Posts: n/a
 
      11-05-2003
Dan Pop <(E-Mail Removed)> scribbled the following:
> In <bob3ic$nb4$(E-Mail Removed)> Joona I Palaste <(E-Mail Removed)> writes:
>>Dan Pop <(E-Mail Removed)> scribbled the following:
>>> In <boalcr$eg7$(E-Mail Removed)> Joona I Palaste <(E-Mail Removed)> writes:
>>>>And even if that's true, there's no guarantee the host CPU returns
>>>>scalars and pointers in the same way. It could use different registers,
>>>>for instance, in which case p2 will be pure garbage.

>>
>>> Huh? I can see no function call in the code. What am I missing?

>>
>>You're missing the fact that I can sometimes fumble up in my
>>terminology. By "return" I meant something like "store". Is a cast to
>>an (int *) allowed to read from a different register than a cast to a
>>(long)?


> Now, you're severely confused: the evaluation of an expression is defined
> in terms of values, it is immaterial where these values are stored, as
> long as all of them are obtained via legit means. It is compiler's job
> to do the right thing and it has all the necessary information for that.


> Such things can happen only when misdeclared functions are involved.
> Consider the following *complete* program (on a C89 implementation):


> int main()
> {
> return sin(0.0);
> }


> In the absence of an explicit declaration, sin() is implicitly declared
> as returning int. Therefore, after generating the function call, the
> compiler will expect the return value to be in whatever place a function
> returning int will put its return value. But the sin() function doesn't
> "know" that and it will put its return value in whatever place a function
> returning double is supposed to put its return value. The final result
> being that return will use an indeterminate value (but undefined behaviour
> has already been invoked by the time sin() was called.


Thanks, Dan! You deconfused me pretty well. So in other words, when
evaluating the expressions, the compiler "knows" the correct types and
the register mix-up I was talking about can't happen. But when the
compiler is evaluating function calls, it doesn't necessarily "know" how
the return values of the functions will be used.

--
/-- Joona Palaste ((E-Mail Removed)) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"You can pick your friends, you can pick your nose, but you can't pick your
relatives."
- MAD Magazine
 
Reply With Quote
 
Arthur J. O'Dwyer
Guest
Posts: n/a
 
      11-05-2003

On Wed, 5 Nov 2003, Joona I Palaste wrote:
>
> Dan Pop <(E-Mail Removed)> scribbled the following:
> > Joona I Palaste <(E-Mail Removed)> writes:
> >>And even if that's true, there's no guarantee the host CPU returns
> >>scalars and pointers in the same way. It could use different registers,
> >>for instance, in which case p2 will be pure garbage.

>
> > Huh? I can see no function call in the code. What am I missing?

>
> You're missing the fact that I can sometimes fumble up in my
> terminology. By "return" I meant something like "store". Is a cast to
> an (int *) allowed to read from a different register than a cast to a
> (long)?


(ITYM: Is an implementation allowed to make conversions between
[non-intptr_t] integral and pointer types do funky, unpredictable
stuff?)

Technically, yes, as long as the implementation documents that
behavior (N869 6.3.2.3#5). Of course, that would be a pretty silly
implementation; it'd be much more user-friendly to simply convert all
pointers to zero upon conversion to 'long'.

And no, no *sensible* compiler would ever do such a thing. I
don't think it would simplify anything if one made the compiler
do that.

-Arthur
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
checking casts Dan Upton Java 4 12-01-2005 06:20 PM
Web casts in ASP.Net =?Utf-8?B?Q2hyaXMgRGF2b2xp?= ASP .Net 1 10-19-2005 09:45 PM
cannot convert parameter from 'double (double)' to 'double (__cdecl *)(double)' error Sydex C++ 12 02-17-2005 06:30 PM
Needless casts? Joona I Palaste Java 15 04-25-2004 10:14 PM
Re: = operator should automatically perform appropriate casts cgbusch Java 2 07-08-2003 03:58 PM



Advertisments