473,739 Members | 5,405 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Richard heathfields casting operation

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 *, ...))

Nov 7 '07 #1
17 2225
so**********@gm ail.com 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
Nov 7 '07 #2
Richard Heathfield wrote:
so**********@gm ail.com 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(*)(cons t 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 <atdoc.ic.ac. uk
Nov 7 '07 #3
On Nov 7, 7:05 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
sophia.ag...@gm ail.com 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)fa hr <= (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

Nov 7 '07 #4
so**********@gm ail.com 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)fa hr <= (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.
Nov 7 '07 #5
Philip Potter said:
Richard Heathfield wrote:
> so**********@gm ail.com 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
Nov 7 '07 #6
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.)
Nov 7 '07 #7
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 <atdoc.ic.ac. uk
Nov 7 '07 #8
Spoon <root@localhost writes:
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.
I wouldn't be surprised.
(Linux/IA-64 is one such platform.)
Is it? void* and function pointers are both 8 bytes on Linux/IA-64.
I don't see any reason why it shouldn't work (unless the compiler
chooses to forbid it), and it works for me with at least one example:
=============== =============== ==========
% uname -a
Linux tg-login1 2.4.21-314.tg1 #1 SMP Tue Nov 21 15:49:16 CST 2006 ia64 unknown
% cat c.c
#include <stdio.h>

typedef int (*pointer_to_pr intf)(char *, ...);

int main(void)
{
void *p = printf;

printf("sizeof( void*) = %d\n", (int)sizeof(voi d*));
printf("sizeof( pointer_to_prin tf) = %d\n", (int)sizeof(poi nter_to_printf) );
((pointer_to_pr intf)p)("p = %p\n", p);
((pointer_to_pr intf)p)("printf = %p\n", (void*)printf);

return 0;
}
% ./c
sizeof(void*) = 8
sizeof(pointer_ to_printf) = 8
p = 0x2000000000039 608
printf = 0x2000000000039 608
=============== =============== ==========

Of course this doesn't prove anything, but I'm curious why you think
that such conversions will break on Linux/IA-64.

(BTW, I don't know how much longer I'll have access to that system.)

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Nov 7 '07 #9
In article <fg**********@a ioe.orgPhilip Potter <pg*@see.sig.in validwrites:
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.
But was it a bug? Ah, yes, it is. The first conversion is allowed, but
is implementation defined, but the second conversion is not necessarily
allowed, because it can be undefined behavior.
And you just highlighted Yet Another Reason not to add
spurious casts.

Indeed.
Morover, the original did show how easy it is to get complex casts right.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 8 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
3478
by: Jacob Jensen | last post by:
This question has probably been asked a million time, but here it comes again. I want to learn the difference between the three type cast operators: static_cast, reinterpret_cast, dynamic_cast. A good way to do this is by example. So I will give an example and please tell me what you think: I have a base class A with a virtual destructor, and a class B that is it inherits publicly from A and defines som extra stuff.
19
1753
by: Ramesh Tharma | last post by:
Hi, Is any one knows what's wrong with the following code, I was told that it will compile and run but it will crash for some values. Assume that variables are initilized. char* c; long* lg;
43
1860
by: sophia.agnes | last post by:
Hi, I was going through Mr "Richard heathfields" site , it is written as follows:- Some people think C has no role to play in the modern programming world. I would consider this opinion to have rather more validity if it weren't for the fact that even those who express it use C code on a daily basis (whether they realise it or not). C programs and libraries are woven into the very fabric of the modern programming world, and
3
1763
by: George Orwell | last post by:
hay, Han frm china heer again... ben readin sum more c unleashed book dick heathfields book... still readin dick heathfields data structs cht but jumped ahead to chad dixons cgi proggraming cht out of interest for bit varietty... hard to focuss on length of data structs cht vry drawn out longwindded imho... small robusttness patch for pg. 400 DlExchange() function: int DLExchange(DLLIST *ItemA, DLLIST *ItemB)
0
9479
Oralloy
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9337
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9266
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8215
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6054
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4570
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4826
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
2748
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2193
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.