Velocity Reviews > Crazy (?) C problem

# Crazy (?) C problem

Old Wolf
Guest
Posts: n/a

 01-16-2005
Peter Nilsson wrote:
> CBFalconer wrote:
> > Jason Sewall wrote:
> > >

> > ... snip ...
> > >
> > > gf->invdim = 1.0/(double)dim;
> > > printf("invdim: %f\n", (float)gf->invdim);

> >
> > printf is a variadic function. %f expects a double argument. You
> > are casting the argument to a float, thus invoking undefined
> > behaviour.

>
> Not directly. It's only undefined behaviour if gf->invdim is not
> representable as a float.

It's only undefined if gf->invdim is outside the range of float.
If it is in the range but not representable exactly as float, then
it must be rounded to one of the two nearest values in an I-D manner
(that's how I am reading C99, anyway).

Also, some people have suggested the cast is pointless. It would
be useful if you wanted to investigate what happened when the
double in question is rounded to a float (for example, if you had
noticed strange behaviour when calling a function prototyped
to take a float parameter).

Keith Thompson
Guest
Posts: n/a

 01-16-2005
"Mike Wahler" <(E-Mail Removed)> writes:
> "Jason Sewall" <(E-Mail Removed)> wrote in message
> news:41eaa722\$(E-Mail Removed)...
>> About the explicit double cast;
>> this has no effect on the code, correct?

>
> It could give incorrect results.
> It could slow it down (but probably not noticeably).
>
>> I prefer an explicit cast

>
> casting is explicit by definition.
>
>> where possible to eliminate any confusion.

>
> It exposes *your* confusion about how C works.

That's a little harsh. The original context (lost in the followups)
was:

gf->invdim = 1.0/(double)dim;
printf("invdim: %f\n", (float)gf->invdim);

where dim is an integer and gv->invdim isa double.

The constant 1.0 is of type double (as is any unsuffixed floating
constant), so if the cast is omitted:

1.0/dim

the value of dim will be converted to double. The cast, in this
particular case, is redundant but harmless.

Casts are inherently suspicious because they do too much, and C has
enough implicit conversions that casts are usually unnecessary. In
many cases, a cast tells the compiler "I know what I'm doing; shut up
and doing what I say" -- which is dangerous if you *don't* know what
you're doing. The classic example is casting the result of malloc(),
which can (in C90) mask the error of omitting the "#include <stdlib.h>".

But casts from one numeric type to another are *relatively* harmless,
since they convert the value rather than just copying the bits (as
pointer casts often do).

Casts are like gotos. They have legitimate uses, but their abuse has
caused any use of them to be suspicious.

[...]

>> As for comments about including stdio.h, it has been included outside
>> the snippet shown here.

And we had no way of knowing that.

> It's always best to post compilable code if at all possible.
> If your code is large, pare it down to a (still compilable)

That's good advice. In fact, in the process of narrowing down your
code to a small compilable snippet, you'll often solve the problem
yourself.

But this case may be one of the rare exceptions. The symptom was
showing up in a 2-line code snippet. Duplicating that snippet changed
the symptoms, which didn't make much sense. It might not have been
possible to narrow down the program while still exhibiting the
problem.

[...]

>> At any rate, the only think I can think of is that I have some
>> assignment to a void pointer somewhere that's corrupting the data in the
>> program. Whatever, I'll just use the release mode to get the project
>> finished. I'll clean up the code later and see if the bug shows up.

What do you mean by "assignment to a void pointer"? Do you mean a
null pointer?

Probably something executed before the snippet you showed us invoked
undefined behavior and corrupted something somewhere. There are
numerous things that can cause undefined behavior.

Compile your code with the highest possible warning and optimization
levels (higher optization levels cause the compiler to do more
analysis, which can allow it to detect more errors). Run it under a
debugger. Examine everything you can, including address and values of
variables (gf is a pointer; see what address it points to). If
anything looks odd, trace back in your program and see how it got that
way.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <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.

Mike Wahler
Guest
Posts: n/a

 01-17-2005

"Keith Thompson" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> "Mike Wahler" <(E-Mail Removed)> writes:
> > "Jason Sewall" <(E-Mail Removed)> wrote in message
> > news:41eaa722\$(E-Mail Removed)...
> >> About the explicit double cast;
> >> this has no effect on the code, correct?

> >
> > It could give incorrect results.
> > It could slow it down (but probably not noticeably).
> >
> >> I prefer an explicit cast

> >
> > casting is explicit by definition.
> >
> >> where possible to eliminate any confusion.

> >
> > Your code can *cause* confusion by giving a wrong answer.
> > It exposes *your* confusion about how C works.

>
> That's a little harsh.

Perhaps. That wasn't my intention.

> The original context (lost in the followups)
> was:
>
> gf->invdim = 1.0/(double)dim;
> printf("invdim: %f\n", (float)gf->invdim);
>
> where dim is an integer and gv->invdim isa double.
>
> The constant 1.0 is of type double (as is any unsuffixed floating
> constant), so if the cast is omitted:
>
> 1.0/dim
>
> the value of dim will be converted to double. The cast, in this
> particular case, is redundant but harmless.

I was talking about the cast of 'invdim' to 'float'.

>
> Casts are inherently suspicious because they do too much, and C has
> enough implicit conversions that casts are usually unnecessary. In
> many cases, a cast tells the compiler "I know what I'm doing; shut up
> and doing what I say" -- which is dangerous if you *don't* know what
> you're doing.

In this case (the cast to 'float') I think that is the case.

> The classic example is casting the result of malloc(),
> which can (in C90) mask the error of omitting the "#include <stdlib.h>".
>
> But casts from one numeric type to another are *relatively* harmless,
> since they convert the value rather than just copying the bits (as
> pointer casts often do).

But my point was that casting a double to a float
can lose information.

>
> Casts are like gotos. They have legitimate uses, but their abuse has
> caused any use of them to be suspicious.

Yes.

>
> > It's always best to post compilable code if at all possible.
> > If your code is large, pare it down to a (still compilable)

>
> That's good advice. In fact, in the process of narrowing down your
> code to a small compilable snippet, you'll often solve the problem
> yourself.

Yes.

>
> But this case may be one of the rare exceptions. The symptom was
> showing up in a 2-line code snippet. Duplicating that snippet changed
> the symptoms, which didn't make much sense. It might not have been
> possible to narrow down the program while still exhibiting the
> problem.

I was responding to OP's:

"About the printf formatting: I thought %f expected a float, not a
double, hence the cast."

-Mike

Keith Thompson
Guest
Posts: n/a

 01-17-2005
"Mike Wahler" <(E-Mail Removed)> writes:
> "Keith Thompson" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...

[...]
>> That's a little harsh.

>
> Perhaps. That wasn't my intention.
>
>> The original context (lost in the followups)
>> was:
>>
>> gf->invdim = 1.0/(double)dim;
>> printf("invdim: %f\n", (float)gf->invdim);
>>
>> where dim is an integer and gv->invdim isa double.
>>
>> The constant 1.0 is of type double (as is any unsuffixed floating
>> constant), so if the cast is omitted:
>>
>> 1.0/dim
>>
>> the value of dim will be converted to double. The cast, in this
>> particular case, is redundant but harmless.

>
> I was talking about the cast of 'invdim' to 'float'.

Sorry, I missed that; I thought you were talking about (double)dim.

The cast to float is also a numeric-to-numeric cast, so it doesn't
have the same pitfalls that pointer casts can have, but yes, it does
potentially lose information.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <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.

Lawrence Kirby
Guest
Posts: n/a

 01-17-2005
On Sat, 15 Jan 2005 23:54:39 -0500, Jason Sewall wrote:

> Sorry, here's a quick followup (very quick, I posted the parent just two
> minutes ago).
>
> I compiled it with intel 8.0 in "Release" mode. No problem. (The problem
> described in parent occured in intel "debug" mode.
>
> In MSVC 6 Debug, no problem. Ditto for Release.
>
> There must be some sort of bug in my program that only intel debug
> exposes, a bug in intel, or some weird debug setting that I don't
> understand.

There's nothing obviously wrong in the code you posted. There could easily
be something wrong in the code you haven't posted which ends up affecting
the output of this code. You may alternatively have found a genuine
compiler bug. In order to investigate this further you should create a
minimal program that demonstrates the problem. That should be easy enough
to do by cutting down your existing program until just before the point
where the code works. Hopefully you will then have a program small enough
to post in its entirety.

Lawrence

 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 OffTrackbacks are On Pingbacks are On Refbacks are Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post JavaEnquirer Java 7 02-27-2006 10:30 AM Mr Newbie ASP .Net 3 09-22-2005 05:20 AM alef@xs4all.nl C Programming 3 07-27-2005 04:37 AM dr greg Computer Support 7 01-14-2005 09:13 PM ccs Cisco 0 07-30-2004 02:38 AM