Question about mixed scalar type operation

L

linq936

Hi,
I have this little test program:

#include <stdio.h>

int main(){
float f1 = 2.2;
double d1 = 3.3;
int j = f1 * d1;
int i = (int) f1 * d1;
int i2 = (int) (f1 * d1);
printf("%d, i=%d, j=%d, i2=%d\n", f1*d1, i, j, i2);
}

I use gcc on Linux to compile it, there is no warning and the result
is like this:
 
C

Chris Dollin

Hi,
I have this little test program:

#include <stdio.h>

int main(){
float f1 = 2.2;
double d1 = 3.3;
int j = f1 * d1;
int i = (int) f1 * d1;
int i2 = (int) (f1 * d1);
printf("%d, i=%d, j=%d, i2=%d\n", f1*d1, i, j, i2);
}

I use gcc on Linux to compile it, there is no warning and the result
is like this:

Well, if you got /no/ output, that's surprising but allowed, since
the expression `f1*d1` is of type double and you're trying to print
it through `%d`, which requires an `int`; undefined behaviour, anything
can happen in the next half-hour.

Compile with warnings turned up: gcc spots (some, compile-time-visible)
format mismatches.

(fx:muse) Shouldn't it be possible for an implementation to arrange to
pass to the printf-family a description of the actual types of the arguments,
so that the called function could check the requested conversions against
the type list? Since it would be implementation magic, it wouldn't need
to be expressible in Standard C. You'd only need to use the full power
of the machinery when the format and arguments weren't both visible at
compile-time. And since it's IO conversion, the cost of the check should
be small compared to the cost of the call.
 
D

David Thompson

(fx:muse) Shouldn't it be possible for an implementation to arrange to
pass to the printf-family a description of the actual types of the arguments,
so that the called function could check the requested conversions against
the type list? Since it would be implementation magic, it wouldn't need
to be expressible in Standard C. You'd only need to use the full power
of the machinery when the format and arguments weren't both visible at
compile-time. And since it's IO conversion, the cost of the check should
be small compared to the cost of the call.

You would have to choose whether to use it for all vararg calls, or
only *printf/scanf. The former might be bad but might be good. The
latter would have less impact, but is one more thing to implement and
support, or really one and a half: some magic, pehaps an attribute, to
distinguish the special targets, plus the special mechanism.

As an alternative to actually passing to *printf/scanf, you could have
a preliminary format-validate function that is auto-called for
variable formats, perhaps only once per value (e.g. hoisted above a
loop), equivalent to the check now done at compile time by gcc.

The complete type includes the length of strings (char arrays); this
information won't be easily available at the call site in many cases.
If you leave that part out, and only check %d-to-int etc., it's easy
enough, but not quite complete.

And of course *printf/scanf is only a small part of the problem; there
are still zillions of other places in C you can easily cause UB, most
of which can't be (nearly) fixed so easily. This seems kind of like
putting a blade guard on one-eighth of the blade; it will help in some
cases, but can give a false sense or at least suggestion of safety
that may hurt in more cases than it helps. If you want a safe HLL,
even a safe efficient HLL, C is not a very good place to start.

And since languages that are safe are easily enough available and in
most cases easily enough interoperable with C, why waste the effort?

- formerly david.thompson1 || achar(64) || worldnet.att.net
 

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

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top