Why aren't signed/unsigned type clashes checked?

C

Clint Olsen

I just wrote some quick tests and my compiler (gcc) doesn't seem to flag
passing signed arguments to functions expecting unsigned types (and
presumably vice versa). Is there any particular reason why this is not
considered at least something worthy of a warning? I know that some
implementations complain when you don't get the formatting arguments
correct for printf(), but I would think something like this should be
enforced more strictly.

Thanks,

-Clint
 
T

Tom St Denis

Clint said:
I just wrote some quick tests and my compiler (gcc) doesn't seem to flag
passing signed arguments to functions expecting unsigned types (and
presumably vice versa). Is there any particular reason why this is not
considered at least something worthy of a warning? I know that some
implementations complain when you don't get the formatting arguments
correct for printf(), but I would think something like this should be
enforced more strictly.

Yup, you're right even with "-Wall -W -std=c99 -pedantic" it doesn't
cause a diagnostic.

I'm going to assume there is a -W flag for that particular warning
[though I don't know what it is off the top of my head].

For the most part that really isn't an "error" since the function is
prototyped the compiler will just cast it to (int) before passing it to
the function.

Just as if it were double and you passed "1" [which is by default an int].

Tom
 
E

Eric Sosman

Clint said:
I just wrote some quick tests and my compiler (gcc) doesn't seem to flag
passing signed arguments to functions expecting unsigned types (and
presumably vice versa). Is there any particular reason why this is not
considered at least something worthy of a warning? I know that some
implementations complain when you don't get the formatting arguments
correct for printf(), but I would think something like this should be
enforced more strictly.

First off, it's perfectly legal C. Function prototypes
don't require that you supply an expression whose type matches
the argument, instead, they cause the supplied value to be
converted to the argument type. You'll get a diagnostic for
impossible conversions (e.g., sqrt("two")), but sqrt(2) and
sqrt(2.0) are effectively identical.

There's a hint in Henry Spencer's "Ten Commandments for C
Programmers" that there may have been debate when prototypes
were being invented about whether they should behave this way.
That is, there may have been a faction that wanted sqrt(2) to
generate an error instead of generating a conversion. If there
was such a debate (I wasn't there), it must have been resolved
the other way, possibly on grounds of convenience and possibly
to avoid breaking old programs.

The convenience and potential breakage would probably have
been large, too. For example, here's a piece of innocent-looking
code that would break if prototypes were "enforceable:"

char buff[20];
memset (buff, 0, 20);

.... because `20' is an `int', and the third argument to memset()
must be a `size_t'. Now, it's easy to argue (and I'd agree)
that `sizeof buff' is a far better way to spell `20', but it's
not always that easy:

right_justify(string, length)
char *string;
int length;
{
int datalen = strlen(string);
memmove (string + length - datalen, string, datalen + 1);
memset (string, ' ', length - datalen);
}

Again, superior practice would use `size_t' values instead of `int',
but `size_t' didn't even exist when these debates (may have) taken
place; masses and masses of pre-existing code used `int' to count
things, and the acceptance of the then-nascent Standard would have
been adversely affected if all those masses of code suddenly stopped
compiling. "For no good reason," at that. As the Rationale puts it:

Existing code is important, existing implementations
are not. A large body of C code exists of considerable
commercial value. Every attempt has been made to ensure
that the bulk of this code will be acceptable to any
implementation conforming to the Standard. The C89
Committee did not want to force most programmers to
modify their C programs just to have them accepted by
a conforming translator.

Of course, a decade and a half have elapsed since prototypes
came on the scene, and the landscape may have changed -- Y2K
alone may have put quite a lot of older code to rest. A practice
that was virtually universal in Olden Days may now have become
rare enough to warrant the "suspicious" label today. (On the
other hand, it may have become more common: sqrt(2) is all right
now, but was an error before prototypes came along.) If you have
the patience, try using gcc with the "-Wconversion" option to
compile some large body of existing code; the big question is
whether the resulting diagnostics will be useful or just noisy.
 
C

Clint Olsen

First off, it's perfectly legal C. Function prototypes
don't require that you supply an expression whose type matches
the argument, instead, they cause the supplied value to be
converted to the argument type. You'll get a diagnostic for
impossible conversions (e.g., sqrt("two")), but sqrt(2) and
sqrt(2.0) are effectively identical.

There's a hint in Henry Spencer's "Ten Commandments for C
Programmers" that there may have been debate when prototypes
were being invented about whether they should behave this way.
That is, there may have been a faction that wanted sqrt(2) to
generate an error instead of generating a conversion. If there
was such a debate (I wasn't there), it must have been resolved
the other way, possibly on grounds of convenience and possibly
to avoid breaking old programs.

Thanks for the detailed explanation. I would counter to this mindset that
while we don't want to break existing code and allow sensible type
promotions to occur, we should be able to tell the compiler to optionally
flag these as warnings (or info). Gcc has enough goofy warnings already.

-Clint
 
C

Carsten Hansen

Clint Olsen said:
I just wrote some quick tests and my compiler (gcc) doesn't seem to flag
passing signed arguments to functions expecting unsigned types (and
presumably vice versa). Is there any particular reason why this is not
considered at least something worthy of a warning? I know that some
implementations complain when you don't get the formatting arguments
correct for printf(), but I would think something like this should be
enforced more strictly.

Thanks,

-Clint

There are other compilers than gcc. CodeWarrior from Metrowerks will flag
it.
I'm sure some lint programs will flag it as well.

Carsten Hansen
 
E

Eric Sosman

Clint said:
Thanks for the detailed explanation. I would counter to this mindset that
while we don't want to break existing code and allow sensible type
promotions to occur, we should be able to tell the compiler to optionally
flag these as warnings (or info). Gcc has enough goofy warnings already.

... including "-Wconversion". Is it close enough to
what you're looking for? (Note that it is *not* among those
enabled by "-W -Wall".)
 
C

Clint Olsen

... including "-Wconversion". Is it close enough to what you're looking
for? (Note that it is *not* among those enabled by "-W -Wall".)

Ahh yes, just what the doctor ordered. I can see why they don't
necessarily turn this on by default. It gets damn chatty even with legal
code...

-Clint
 
C

Clint Olsen

There are other compilers than gcc. CodeWarrior from Metrowerks will flag
it. I'm sure some lint programs will flag it as well.

I have access to both the Intel Compiler and GCC, and both of those (by
default) behaved as I described. So, it wasn't like I had my head buried
in the proverbial "GCC sand."

-Clint
 
S

Shill

I have access to both the Intel Compiler and GCC, and both of those (by
default) behaved as I described. So, it wasn't like I had my head buried
in the proverbial "GCC sand."

The online version of the GCC manual has an Option Index:
http://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Option-Index.html

As Eric Sosman pointed out, -Wconversion looks promising.

Warn if a prototype causes a type conversion that
is different from what would happen to the same
argument in the absence of a prototype. This includes
conversions of fixed point to floating and vice versa,
and conversions changing the width or signedness of a
fixed point argument except when the same as the
default promotion.

Also, warn if a negative integer constant expression
is implicitly converted to an unsigned type. For example,
warn about the assignment x = -1 if x is unsigned. But
do not warn about explicit casts like (unsigned) -1.
 
P

Philipp Thomas

Eric said:
... including "-Wconversion". Is it close enough to
what you're looking for?

-Wconversion is nearly useless for ISO/ANSI C. It's meant to be used
when converting K&R to ISO/ANSI C code. In this case the different
handling of arguments can lead to quite a few surprises in code that
doesn't expect it.

Philipp
 
D

Dan Pop

In said:
First off, it's perfectly legal C. Function prototypes
don't require that you supply an expression whose type matches
the argument, instead, they cause the supplied value to be
converted to the argument type. You'll get a diagnostic for
impossible conversions (e.g., sqrt("two")), but sqrt(2) and
sqrt(2.0) are effectively identical.

There's a hint in Henry Spencer's "Ten Commandments for C
Programmers" that there may have been debate when prototypes
were being invented about whether they should behave this way.
That is, there may have been a faction that wanted sqrt(2) to
generate an error instead of generating a conversion. If there
was such a debate (I wasn't there), it must have been resolved
the other way, possibly on grounds of convenience and possibly
to avoid breaking old programs.

Actually, the idea is very simple: conversion is performed as if by
assignment. You couldn't outlaw sqrt(2) without equally outlawing
double x = 2. Otherwise, the language would have become a mess.

It's already quite messy in this area, for backward compatibility
with K&R C: "strange" type conversions occur when non-prototyped or
variadic functions are called (integral promotions and floats get
expanded to doubles). People who never used pre-ANSI C must be quite
disgusted when they learn these rules (and very motivated to avoid
calling unprototyped functions, even if they have to live with variadic
functions). Making another set of more or less arbitrary rules for
prototyped functions would have been unacceptable, while conversion as
if by assignment is a very natural solution.

Requiring perfect matches would have simply resulted in plenty of casts
in the function calls, whenever the argument type didn't match the
parameter type, which happens quite often in practice.

Dan
 

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,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top