Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Richard heathfields casting operation

Reply
Thread Tools

Richard heathfields casting operation

 
 
sophia.agnes@gmail.com
Guest
Posts: n/a
 
      11-07-2007
Hi ,

I was going through peter van der linden's book Expert C programming,
in this book there is a section named "How and why to cast"

the author then says as follows

(float) 3 - it's a type conversion and the actual bits change.
if you say (float) 3.0 it is a type disambiguation,and the compiler
can plant the correct bits in the first place.some people say that
casts are so named because they help something broken to limp along.

what exactly is this type disambiguation...????
i have n't seen any casts like (float) 3.0; in use (may be due to my
limited experience). how will it help the compiler to plant the
correct bits????

Then the author says that as an impratical example ,you can create a
pointer to ,for example printf(), with

extern int printf(const char*,...);
voif *f = (void *) printf;

you can then call printf through a properly cast pointer, in this
manner:

(*(int(*)(const char*,...))f)("Bite my shorts. Also my chars and ints
\n");

now void *f = (void *) printf; why this cast is required....????
^^^^^^
why the author says that above example is impractical...???
why is it because library functions are not meant to be called via
void pointer.....?????

for explanation of above issues i went to Richard heathfields site:
http://www.cpax.org.uk/prg/writings/casting.php

there i found nothing mentioned about type disambiguation..
but i found more complex example such as this

(int)((int (*)(const char *, ...))
printf((const char *)"%3.0f %6.1f\n",
(float)fahr, (float)celsius));

what exactly does this statement does...???

is it just simple printf such as this....
printf("%3.0f %6.1f\n",fahr, celsius);

why all these redundant casts such as

1)(const char *)"%3.0f %6.1f\n"
2)(int)((int (*)(const char *, ...))

 
Reply With Quote
 
 
 
 
Chris Dollin
Guest
Posts: n/a
 
      11-07-2007
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> I was going through peter van der linden's book Expert C programming,
> in this book there is a section named "How and why to cast"
>
> Then the author says that as an impratical example ,you can create a
> pointer to ,for example printf(), with
>
> extern int printf(const char*,...);
> voif *f = (void *) printf;


That's not portable; there's no guarantee that a pointer-to-function
will fit in a pointer-to-void (and on some implementations, it
doesn't).

>
> for explanation of above issues i went to Richard heathfields site:
> http://www.cpax.org.uk/prg/writings/casting.php
>
> there i found nothing mentioned about type disambiguation..
> but i found more complex example such as this
>
> (int)((int (*)(const char *, ...))
> printf((const char *)"%3.0f %6.1f\n",
> (float)fahr, (float)celsius));
>
> what exactly does this statement does...???


The text of that page explains what's going on. Here's a quote:

Believe it or not, those casts are all "correct". And yes, the code
works just fine. But suddenly the code isn't quite as easy to read,
is it? So much for self-documentation.

--
Chris "3." Dollin

Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

 
Reply With Quote
 
 
 
 
Richard Heathfield
Guest
Posts: n/a
 
      11-07-2007
(E-Mail Removed) said:

> Hi ,
>
> I was going through peter van der linden's book Expert C programming,
> in this book there is a section named "How and why to cast"
>
> the author then says as follows
>
> (float) 3 - it's a type conversion and the actual bits change.
> if you say (float) 3.0 it is a type disambiguation,and the compiler
> can plant the correct bits in the first place.some people say that
> casts are so named because they help something broken to limp along.


In my edition, it says (double) 3 and (double) 3.0 - he's right about the
conversion but wrong about the disambiguation, since 3.0 is of type
double, so casting it to double doesn't disambiguate anything, as there is
no ambiguity to disambiguate.

> what exactly is this type disambiguation...????


Absent.

> i have n't seen any casts like (float) 3.0; in use (may be due to my
> limited experience). how will it help the compiler to plant the
> correct bits????


If you need a float with the value 3.0f, just say 3.0f - there is no need
to cast.

>
> Then the author says that as an impratical example ,you can create a
> pointer to ,for example printf(), with
>
> extern int printf(const char*,...);
> voif *f = (void *) printf;


Whilst this is a common extension, the Standard does not guarantee that you
can store a function pointer in a void * without losing information.
Better to do this (in which case no cast is required):

int (*f)(const char *, ...) = printf;

>
> you can then call printf through a properly cast pointer, in this
> manner:
>
> (*(int(*)(const char*,...))f)("Bite my shorts. Also my chars and ints
> \n");


Not guaranteed as written. But with my suggested change, you don't need to
cast. You just do either (*f)("Bite...\n"); or even simply f("Bite...\n");
at your discretion.

>
> now void *f = (void *) printf; why this cast is required....????
> ^^^^^^


The code is broken. Don't use it.

> why the author says that above example is impractical...???


Perhaps because the code is broken.

> why is it because library functions are not meant to be called via
> void pointer.....?????


Because the Standard doesn't guarantee that it's possible.

> for explanation of above issues i went to Richard heathfields site:
> http://www.cpax.org.uk/prg/writings/casting.php
>
> there i found nothing mentioned about type disambiguation..


Right. There's no need for it. Casting is not about disambiguation.

> but i found more complex example such as this
>
> (int)((int (*)(const char *, ...))
> printf((const char *)"%3.0f %6.1f\n",
> (float)fahr, (float)celsius));
>
> what exactly does this statement does...???


It's a kind of picture. Some people claim that casts "clarify" code. This
picture takes them at their word. Which do you think is clearer - the
above, or printf("%3.0f %6.1f\n", fahr, celsius))? I know which one I'd
choose.

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
 
Reply With Quote
 
Philip Potter
Guest
Posts: n/a
 
      11-07-2007
Richard Heathfield wrote:
> (E-Mail Removed) said:
>
>> Hi ,
>>
>> I was going through peter van der linden's book Expert C programming,
>> in this book there is a section named "How and why to cast"
>>
>> the author then says as follows
>>
>> (float) 3 - it's a type conversion and the actual bits change.
>> if you say (float) 3.0 it is a type disambiguation,and the compiler
>> can plant the correct bits in the first place.some people say that
>> casts are so named because they help something broken to limp along.

>
> In my edition, it says (double) 3 and (double) 3.0 - he's right about the
> conversion but wrong about the disambiguation, since 3.0 is of type
> double, so casting it to double doesn't disambiguate anything, as there is
> no ambiguity to disambiguate.
>
>> what exactly is this type disambiguation...????

>
> Absent.
>
>> i have n't seen any casts like (float) 3.0; in use (may be due to my
>> limited experience). how will it help the compiler to plant the
>> correct bits????

>
> If you need a float with the value 3.0f, just say 3.0f - there is no need
> to cast.
>
>> Then the author says that as an impratical example ,you can create a
>> pointer to ,for example printf(), with
>>
>> extern int printf(const char*,...);
>> voif *f = (void *) printf;

>
> Whilst this is a common extension, the Standard does not guarantee that you
> can store a function pointer in a void * without losing information.
> Better to do this (in which case no cast is required):
>
> int (*f)(const char *, ...) = printf;
>
>> you can then call printf through a properly cast pointer, in this
>> manner:
>>
>> (*(int(*)(const char*,...))f)("Bite my shorts. Also my chars and ints
>> \n");

>
> Not guaranteed as written. But with my suggested change, you don't need to
> cast. You just do either (*f)("Bite...\n"); or even simply f("Bite...\n");
> at your discretion.
>
>> now void *f = (void *) printf; why this cast is required....????
>> ^^^^^^

>
> The code is broken. Don't use it.
>
>> why the author says that above example is impractical...???

>
> Perhaps because the code is broken.
>
>> why is it because library functions are not meant to be called via
>> void pointer.....?????

>
> Because the Standard doesn't guarantee that it's possible.
>
>> for explanation of above issues i went to Richard heathfields site:
>> http://www.cpax.org.uk/prg/writings/casting.php
>>
>> there i found nothing mentioned about type disambiguation..

>
> Right. There's no need for it. Casting is not about disambiguation.
>
>> but i found more complex example such as this
>>
>> (int)((int (*)(const char *, ...))
>> printf((const char *)"%3.0f %6.1f\n",
>> (float)fahr, (float)celsius));
>>
>> what exactly does this statement does...???

>
> It's a kind of picture. Some people claim that casts "clarify" code. This
> picture takes them at their word. Which do you think is clearer - the
> above, or printf("%3.0f %6.1f\n", fahr, celsius))? I know which one I'd
> choose.


Doesn't it call printf, cast the result to 'int (*)(const char *,...)',
then cast it again to 'int'? Shouldn't it therefore be:

(int)(
((int (*)(const char *, ...))printf)
((const char *)"%3.0f %6.1f\n",(float)fahr, (float)celsius)
);

If not, doesn't that mean that the (pointless) cast in the following:

int *x = (int *)malloc(sizeof *x); /* Don't do this. */

is actually casting malloc, not malloc's return value, to 'int *'?

--
Philip Potter pgp <at> doc.ic.ac.uk
 
Reply With Quote
 
sophia.agnes@gmail.com
Guest
Posts: n/a
 
      11-07-2007
On Nov 7, 7:05 am, Richard Heathfield <(E-Mail Removed)> wrote:
> (E-Mail Removed) said:
>
> > Hi ,

>
> > I was going through peter van der linden's book Expert C programming,
> > in this book there is a section named "How and why to cast"

>
> > the author then says as follows

>
> > (float) 3 - it's a type conversion and the actual bits change.
> > if you say (float) 3.0 it is a type disambiguation,and the compiler
> > can plant the correct bits in the first place.some people say that
> > casts are so named because they help something broken to limp along.

>
> In my edition, it says (double) 3 and (double) 3.0 - he's right about the
> conversion but wrong about the disambiguation, since 3.0 is of type
> double, so casting it to double doesn't disambiguate anything, as there is
> no ambiguity to disambiguate.
>
> > what exactly is this type disambiguation...????

>
> Absent.
>
> > i have n't seen any casts like (float) 3.0; in use (may be due to my
> > limited experience). how will it help the compiler to plant the
> > correct bits????

>
> If you need a float with the value 3.0f, just say 3.0f - there is no need
> to cast.
>
>
>
> > Then the author says that as an impratical example ,you can create a
> > pointer to ,for example printf(), with

>
> > extern int printf(const char*,...);
> > voif *f = (void *) printf;

>
> Whilst this is a common extension, the Standard does not guarantee that you
> can store a function pointer in a void * without losing information.
> Better to do this (in which case no cast is required):
>
> int (*f)(const char *, ...) = printf;
>
>
>
> > you can then call printf through a properly cast pointer, in this
> > manner:

>
> > (*(int(*)(const char*,...))f)("Bite my shorts. Also my chars and ints
> > \n");

>
> Not guaranteed as written. But with my suggested change, you don't need to
> cast. You just do either (*f)("Bite...\n"); or even simply f("Bite...\n");
> at your discretion.
>
>
>
> > now void *f = (void *) printf; why this cast is required....????
> > ^^^^^^

>
> The code is broken. Don't use it.
>
> > why the author says that above example is impractical...???

>
> Perhaps because the code is broken.
>
> > why is it because library functions are not meant to be called via
> > void pointer.....?????

>
> Because the Standard doesn't guarantee that it's possible.
>
> > for explanation of above issues i went to Richard heathfields site:
> >http://www.cpax.org.uk/prg/writings/casting.php

>
> > there i found nothing mentioned about type disambiguation..

>
> Right. There's no need for it. Casting is not about disambiguation.
>
> > but i found more complex example such as this

>
> > (int)((int (*)(const char *, ...))
> > printf((const char *)"%3.0f %6.1f\n",
> > (float)fahr, (float)celsius));

>
> > what exactly does this statement does...???

>
> It's a kind of picture. Some people claim that casts "clarify" code. This
> picture takes them at their word. Which do you think is clearer - the
> above, or printf("%3.0f %6.1f\n", fahr, celsius))? I know which one I'd
> choose.
>
> <snip>
>
> --
> Richard Heathfield <http://www.cpax.org.uk>
> Email: -http://www. +rjh@
> Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
> "Usenet is a strange place" - dmr 29 July 1999


i compiled and executed your program:-

#include <stdio.h>
main()
{
float fahr, celsius;
int lower, upper, step;

lower = (int)0; /* lower limit of temperature table */
upper = (int)300; /* upper limit */
step = (int)20; /* step size */

fahr = (float)lower;
while((float)fahr <= (int)upper) {
celsius = (((float)
((float)5.0/(float)9.0)) *
(float)((float)
(((float)fahr-(float)32.0))));

(int)((int (*)(const char *, ...))
printf((const char *)"%3.0f %6.1f\n",
(float)fahr, (float)celsius));

fahr = (float)((float)fahr + (float)step);
}

gcc -o casting casting.c
../casting

i got the following result:-

0 -17.8
20 -6.7
40 4.4
60 15.6
80 26.7
100 37.8
120 48.9
140 60.0
160 71.1
180 82.2
200 93.3
220 104.4
240 115.6
260 126.7
280 137.8
300 148.9

I manually did the calculation for one value by using calculator
for your 220 104.4 values calculator o/p is
219.92 104.4
(calculation done for fahr value based on celsius value 104.4)
so your program is not accurate by a value of .08

 
Reply With Quote
 
Philip Potter
Guest
Posts: n/a
 
      11-07-2007
(E-Mail Removed) wrote:
> i compiled and executed your program:-
>

<snip>

> I manually did the calculation for one value by using calculator
> for your 220 104.4 values calculator o/p is
> 219.92 104.4
> (calculation done for fahr value based on celsius value 104.4)
> so your program is not accurate by a value of .08


Perhaps you should look at your printf() documentation to understand
what this line does:
printf("%3.0f %6.1f\n",fahr, celsius);

Also, please trim the text you quote. It's in general better to quote
too much than too little, but you quoted an entire message to respond to
one point within it.

Phil

--
Philip Potter pgp <at> doc.ic.ac.uk
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      11-07-2007
(E-Mail Removed) wrote:
....
> i compiled and executed your program:-
>
> #include <stdio.h>
> main()
> {
> float fahr, celsius;
> int lower, upper, step;
>
> lower = (int)0; /* lower limit of temperature table */
> upper = (int)300; /* upper limit */
> step = (int)20; /* step size */
>
> fahr = (float)lower;
> while((float)fahr <= (int)upper) {
> celsius = (((float)
> ((float)5.0/(float)9.0)) *
> (float)((float)
> (((float)fahr-(float)32.0))));
>
> (int)((int (*)(const char *, ...))
> printf((const char *)"%3.0f %6.1f\n",
> (float)fahr, (float)celsius));
>
> fahr = (float)((float)fahr + (float)step);
> }
>
> gcc -o casting casting.c
> ./casting
>
> i got the following result:-
>
> 0 -17.8
> 20 -6.7
> 40 4.4
> 60 15.6
> 80 26.7
> 100 37.8
> 120 48.9
> 140 60.0
> 160 71.1
> 180 82.2
> 200 93.3
> 220 104.4
> 240 115.6
> 260 126.7
> 280 137.8
> 300 148.9
>
> I manually did the calculation for one value by using calculator
> for your 220 104.4 values calculator o/p is
> 219.92 104.4
> (calculation done for fahr value based on celsius value 104.4)
> so your program is not accurate by a value of .08


There's no error in his program (as far as I can tell). All you've done
is demonstrated that when floating point values are rounded (as in
general, they must be), they are no longer exact.

The exact value of the Celsius temperature corresponding to 220
Fahrenheit is 104 4/9 = 104.44444.... . Since 9 is not a power of 2,
this value cannot be stored exactly in typical floating point formats,
however in general it will be a very good approximation.

The "%6.1f" format code rounds that approximation to 1 digit after the
decimal place, giving 104.4, exactly as shown by his program. This value
is inaccurate by 4/9-4/10 = 4/90 = 0.044444444.... That is called
roundoff error, and it's a fact of life when doing floating point
calculations. You'll have to get used to it, and you should try to
understand it, otherwise you're likely to write code that produces
nonsense. It is that roundoff error which, when propagated backward,
gives you the 0.08 error in the Fahrenheit temperature.
 
Reply With Quote
 
Richard Heathfield
Guest
Posts: n/a
 
      11-07-2007
Philip Potter said:

> Richard Heathfield wrote:
>> (E-Mail Removed) said:
>>

<snip>
>>>
>>> (int)((int (*)(const char *, ...))
>>> printf((const char *)"%3.0f %6.1f\n",
>>> (float)fahr, (float)celsius));
>>>
>>> what exactly does this statement does...???

>>
>> It's a kind of picture. Some people claim that casts "clarify" code.
>> This picture takes them at their word. Which do you think is clearer -
>> the above, or printf("%3.0f %6.1f\n", fahr, celsius))? I know which one
>> I'd choose.

>
> Doesn't it call printf, cast the result to 'int (*)(const char *,...)',
> then cast it again to 'int'?


Ouch! Yes, it does. Or at least, it did. I've now fixed the example.

That bug has survived unnoticed (or at least unreported) through 6,288 page
views, an average of around 7 per day over 28 months. Congratulations on
spotting it. And you just highlighted Yet Another Reason not to add
spurious casts.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
 
Reply With Quote
 
Spoon
Guest
Posts: n/a
 
      11-07-2007
Richard Heathfield wrote:

> sophia.agnes wrote:
>
>> extern int printf(const char *, ...);
>> void *f = (void *) printf;

>
> Whilst this is a common extension, the Standard does not
> guarantee that you can store a function pointer in a void *
> without losing information.


To emphasize your point, there are real platforms where casting
function pointers to void pointers will break.

(Linux/IA-64 is one such platform.)
 
Reply With Quote
 
Philip Potter
Guest
Posts: n/a
 
      11-07-2007
Richard Heathfield wrote:
> Philip Potter said:
>> Doesn't it call printf, cast the result to 'int (*)(const char *,...)',
>> then cast it again to 'int'?

>
> Ouch! Yes, it does. Or at least, it did. I've now fixed the example.
>
> That bug has survived unnoticed (or at least unreported) through 6,288 page
> views, an average of around 7 per day over 28 months. Congratulations on
> spotting it.


I feel most proud

> And you just highlighted Yet Another Reason not to add
> spurious casts.


Indeed.

--
Philip Potter pgp <at> doc.ic.ac.uk
 
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
Up casting and down casting Sosuke C++ 2 12-20-2009 03:24 PM
Problem with depracated casting method (down casting) Wally Barnes C++ 3 11-20-2008 05:33 AM
posible minour buggs in dick heathfields book Nomen Nescio C Programming 0 10-27-2008 05:40 AM
Richard heathfields C programming article sophia.agnes@gmail.com C Programming 47 11-16-2007 05:41 AM
Another question about inheritance (up-casting and down-casting) kevin Java 11 01-08-2005 07:11 PM



Advertisments