Typecasting in C

A

andynaik

Hi,
Whenever we type in this code
int main()
{
printf("%f",10);
}
we get an error. We can remove that by using #pragma directive t
direct that to the 8087. Even after that the output is 0.00000 and no
10.0000. Can anybody tell me why it is like that and why typecasting i
not done in this case?
-
andynai
 
G

Guest

andynaik said:
Hi,
Whenever we type in this code
int main()
{
printf("%f",10);
}
we get an error. We can remove that by using #pragma directive to
direct that to the 8087. Even after that the output is 0.00000 and not
10.0000. Can anybody tell me why it is like that and why typecasting is
not done in this case??

%f is for double, but 10 is an int.

Rewrite as:
#include <stdio.h>
int main(){printf("%d",10);return 0;}
or as:
#include <stdio.h>
int main(){printf("%f",10.0);return 0;}

- Dario
 
A

Alex Fraser

andynaik said:
Whenever we type in this code
int main()
{
printf("%f",10);
}
we get an error. We can remove that by using #pragma directive to
direct that to the 8087.

Means nothing to me (compiler specifics are off-topic here).
Even after that the output is 0.00000 and not 10.0000. Can anybody tell
me why it is like that and why typecasting is not done in this case??

Read section 15 in the FAQ. Post back if you still have questions.
http://www.eskimo.com/~scs/C-faq/s15.html

Alex
 
E

Emmanuel Delahaye

In 'comp.lang.c' said:
Hi,
Whenever we type in this code
int main()
{
printf("%f",10);
}
we get an error.

Compiling MAIN.C:
Warning MAIN.C 4: Call to function 'printf' with no prototype
Warning MAIN.C 5: Function should return a value
Linking EXE\PROJ.EXE:

This code invokes an undefined behaviour (UB). It is mandatory to supply a
prototype when using a variadic function. Add

#include <stdio.h>

That said, 10 is a int. "%f" is expecting a double. If you want to printf a
double, use 10.0, or the (double) typecast.

Finally, some old Borland C compilers anre buggy and forget to link the
floating point library un such a case. This little hack can help:

#include <stdio.h>

#ifdef __BORLANDC__
/* The pesky "floating point formats not linked" killer hack : */
extern unsigned _floatconvert;
#pragma extref _floatconvert
#endif

int main (void)
{
printf ("%f\n", 10.0);

return 0;
}
 
J

jacob navia

Alex Fraser said:
Means nothing to me (compiler specifics are off-topic here).


Read section 15 in the FAQ. Post back if you still have questions.
http://www.eskimo.com/~scs/C-faq/s15.html

Alex

The FAQ should mention that some compilers DO test the arguments
for sprintf/printf/fprintf etc for validity.

This CAN be done. lcc-win32 does it, and other compilers too.

For instance the above code produces
Warning tx.c: 4 printf argument mismatch for format f. Expected double got
int
0 errors, 1 warnings
 
J

jacob navia

Some compilers DO test the arguments of printf for
validity.
Under lcc-win32 the above code produces:

Warning tx.c: 4 printf argument mismatch for format f. Expected double got
int
0 errors, 1 warnings
 
D

Dan Pop

The FAQ should mention that some compilers DO test the arguments
for sprintf/printf/fprintf etc for validity.

This CAN be done.

ONLY if the compiler can "see" the contents of the format string.
Which is usually the case, but exceptions are not that rare either.

At some point, gcc had the annoying habit of warning if it couldn't
perform such a check (if enabled), because the format was not a
string literal.
lcc-win32 does it, and other compilers too.

Other compilers do a much better job than lcc-win32, when it comes to
format string consistency checks. See below.
For instance the above code produces
Warning tx.c: 4 printf argument mismatch for format f. Expected double got
int
0 errors, 1 warnings

OTOH, lcc-win32 silently accepts printf("%d\n", "foo"), which is very
bad, considering the relative positions of the D and S keys on most
keyboard layouts (i.e. it is a fairly frequent mistake to type d
when you mean s).

Dan
 
J

jacob navia

Dan Pop said:
OTOH, lcc-win32 silently accepts printf("%d\n", "foo"), which is very
bad, considering the relative positions of the D and S keys on most
keyboard layouts (i.e. it is a fairly frequent mistake to type d
when you mean s).

I pondered a long time about that one, since it is perfectly legal to
do:

char *p;
....

printf("The address is %d\n",p);

specially in debugging code.

Granted, this is weird, but how to discriminate between
legal and wrong usage?

But maybe you are right. I added a warning when the "d" format
is used with a pointer.

The "x" format will NOT provoke any warnings.

But this is at the limit of what a compiler can do.
 
D

Dan Pop

I pondered a long time about that one, since it is perfectly legal to
do: ^^^^^^^^^^^^^^^^^^

char *p;
...

printf("The address is %d\n",p);

What have you been smoking recently?
specially in debugging code.

Granted, this is weird, but how to discriminate between
legal and wrong usage?
^^^^^
Can I have a chapter and verse? When did they drop the following
paragraph from the C standard?

9 If a conversion specification is invalid, the behavior is
undefined. If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.

What is the type expected by %d? What is the type of p?
So, the legal usage would be (int)p instead of a plain p, right?
But maybe you are right. I added a warning when the "d" format
is used with a pointer.

The "x" format will NOT provoke any warnings.

Which is just as bad, especially given that x is also a typo candidate
for s.
But this is at the limit of what a compiler can do.

In your humble opinion, what is the purpose of the %p conversion
specification? Why support *anything else* for displaying pointer values?

And if a user *really* wants to use the extra flexibility of the
signed or unsigned integer conversion descriptors, what is preventing
him from casting the pointer to the desired type?

As I said in other threads, you have nothing to lose by using gcc's
behaviour as a guide. If you can benefit from the thought many competent
people have put into the same issue, why reinvent the wheel?

Dan
 
M

Martin Ambuhl

andynaik said:
Hi,
Whenever we type in this code
int main()
{
printf("%f",10);
}
we get an error. We can remove that by using #pragma directive to
direct that to the 8087. Even after that the output is 0.00000 and not
10.0000. Can anybody tell me why it is like that and why typecasting is
not done in this case??

Because you forgot
#include <stdio.h>
You also forgot to terminate the last line of output with an end-of-line
character.

The first mistake, omission of the prototype for a variadic function, is
always an error. The second is an error in code designed to be
portable, and may result in behavior you were not expecting.
 
M

Martin Ambuhl

jacob said:
I pondered a long time about that one, since it is perfectly legal to
do:

char *p;
...

printf("The address is %d\n",p);

The specifier for a pointer is "%p" and it expects a (void *) argument.
This supposedly "legal" line should be
printf("The address is %p\n", (void *)p);

Please stop misleading people who might think you know what you're
talking about.
specially in debugging code.

Granted, this is weird, but how to discriminate between
legal and wrong usage?

You "legal" usage is _wrong_. There is no need to discriminate between
your error and that which is wrong.
 
D

Dan Pop

In said:
Because you forgot
#include <stdio.h>
You also forgot to terminate the last line of output with an end-of-line
character. ^^^^^^^^^^^
^^^^^^^^^
In C, it is called new-line character, even if no line follows. You must
be confusing with the end-of-line *indicator* (which needs not be a
character).
The first mistake, omission of the prototype for a variadic function, is
always an error. The second is an error in code designed to be
portable, and may result in behavior you were not expecting.

Neither of then having anything to do with the real cause of the OP's
problem: type mismatch in a printf call, which will continue to manifest
even after including <stdio.h> and adding the new-line character.

Dan
 
J

jacob navia

The expression

printf("the address is: 0x%x\n",p);

where p is some pointer appears in several million lines in
existing code.

The warnings can become a nuisance and people would stop
using this feature. Personally I think warnings should be
kept to the essential ones, warnings that would uncover a
possible error.

Strictly speaking you should use %p, but I have almost
never seen it in debugging code, where this conversion is
used.

To the contrary of your expectations, I work to make a usable
compiler, not one that will please the purists around c.l.c
 
R

Randy Howard

I pondered a long time about that one, since it is perfectly legal to
do:

char *p;
...

printf("The address is %d\n",p);

specially in debugging code.

I just lost any faith I might have had in lcc-win32. Thanks for
the flashing warning label.
 
D

Dan Pop

In said:
Whenever we type in this code
int main()
{
printf("%f",10);
}
we get an error. We can remove that by using #pragma directive to
direct that to the 8087. Even after that the output is 0.00000 and not
10.0000. Can anybody tell me why it is like that and why typecasting is
not done in this case??

Since type casting is a programming construct, it is you who have to
explain us why you have omitted it from your program.

If your question is why 10 wasn't *automatically converted*, which is
something *completely* different from type casting, the answer is that
it is located in the variable argument part of the printf call and,
therefore, it is subject to the default argument promotions, *only*.
In other words, although the compiler is allowed to have special
knowledge about printf, it is not required to have such knowledge or to
use it for fixing any mismatch between the format string and the rest
of the arguments.

Furthermore, because printf is a variadic function, you *must* provide
a correct declaration for it, before calling it. So, including <stdio.h>
is NOT optional in programs using printf and/or scanf. And a new-line
character in the format string wouldn't hurt, either: the shell prompt
*may* overwrite the last line of output, otherwise. Or be appended to it,
which, even if less destructive, is still far from desirable.

As a last remark, NOW it is the right time to get used to properly
indenting your code.

Dan
 
D

Dan Pop

In said:
Compiling MAIN.C:
Warning MAIN.C 4: Call to function 'printf' with no prototype
Warning MAIN.C 5: Function should return a value
Linking EXE\PROJ.EXE:

You're sorely mistaken if you believe that compiler diagnostics *by
themselves* prove anything at all.
This code invokes an undefined behaviour (UB).

Which means that no diagnostic is required. Furthermore, even if all the
diagnostics of your compiler are fixed, the program is still as broken
as it was in the first place.
It is mandatory to supply a
prototype when using a variadic function. Add

#include <stdio.h>

That said, 10 is a int. "%f" is expecting a double. If you want to printf a
double, use 10.0, or the (double) typecast.

Did you actually try to understand the OP's question? He *knows* that
"%f" is expecting a double and he is asking why the compiler doesn't
convert 10 to double. WHERE are you addressing this question in your
reply?
Finally, some old Borland C compilers anre buggy and forget to link the
floating point library un such a case. This little hack can help:

Since when are some old Borland C compilers topical to this newsgroup?
Aren't they properly handled by the FAQ?

Dan
 
D

Dan Pop

The FAQ should mention that some compilers DO test the arguments
for sprintf/printf/fprintf etc for validity.

But they *still* don't perform any automatic conversions on the arguments,
to make them match the format string (other than the default argument
promotions).

Dan
 
J

jacob navia

Harti Brandt said:
On Tue, 29 Jun 2004, jacob navia wrote:
That has nothing to do with purism. Ever cared to work on a machine where
sizeof(void *) > sizeof(int)?

In the next implementation of lcc-win32 that will be the case (64 bit
machine).

In THAT environment I will issue the warning for all pointer/int
conversions.

In an environment where sizeof(int)==sizeof(void*) many people
(including me) write printf("pointer value=%#x\n",p); to debug
a piece of code. The compiler spitting you hundreds of warnings
would only have the consequence of people IGNORING all warnings.

lcc-win32 has several levels of warnings. After this discussion I have added
a warning when the warning level is higher than normal for all
implicit pointer/int conversions in the printf formats.

It is a pity that people here like to have an atmosphere of
aggresivity that is very boring.

In any case this discussion was positive for me (and lcc-win32).
I have been able to improve lcc-win32 a bit.

Thanks for your time.
 
D

Dan Pop

In said:
The expression

printf("the address is: 0x%x\n",p);

where p is some pointer appears in several million lines in
existing code.

If you think that the amount of existing broken code can prove anything,
you're sorely mistaken. The days when all the world was a 32-bit
platform are gone...
The warnings can become a nuisance and people would stop
using this feature. Personally I think warnings should be
kept to the essential ones, warnings that would uncover a
possible error.

In your stupidity, you don't realise that this is a genuine error, it
just doesn't manifest on *your* platform. Try to engage your brain
and think about platforms with 32-bit int's and 64-bit pointers
(increasingly common since DEC released Alpha OSF/1 in 1992).

To show you that the issue is *real* and not invented ad-hoc:

lx64:~/tmp 11> uname -m
x86_64
lx64:~/tmp 12> cat test.c
#include <stdio.h>

int main(void)
{
int i;
printf("%#x %p\n", &i, (void *)&i);
return 0;
}

lx64:~/tmp 13> gcc test.c
lx64:~/tmp 14> ./a.out
0xbffff00c 0x7fbffff00c
lx64:~/tmp 15> gcc -Wall test.c
test.c: In function `main':
test.c:6: warning: unsigned int format, pointer arg (arg 2)

As you can see, the two values are different: %x has lost information.
So, the people developing their code on your compiler will have a bad
surprise when trying to use it elsewhere and you believe that you're
doing them a favour!
Strictly speaking you should use %p, but I have almost
never seen it in debugging code, where this conversion is
used.

To the contrary of your expectations, I work to make a usable
compiler, not one that will please the purists around c.l.c

If you think you're doing your users any service by not diagnosing
their genuine mistakes, simply because they *accidentally* work on
your platform, you're even more stupid than I thought. People like you
have no business messing with compilers and libraries.

The FAQ *should* contain the following question: "Why should I avoid
lcc-win32 like the plague?". But the answer would significantly increase
its current size...

Dan
 
J

jacob navia

Randy Howard said:
I just lost any faith I might have had in lcc-win32. Thanks for
the flashing warning label.

Mr Howard

It is a pity that people here like to have an atmosphere of
aggresivity that is so boring.

In any case this discussion was positive for me (and lcc-win32).
I have been able to improve lcc-win32 a bit.

Thanks for your time.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top