how can i generate warnings for implicit casts that lose bits?

  • Thread starter robert bristow-johnson
  • Start date
R

robert bristow-johnson

presently using linux gcc:

$ gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --
infodir=/usr/share/info --enable-shared --enable-threads=posix --
enable-checking=release --with-system-zlib --enable-__cxa_atexit --
disable-libunwind-exceptions --enable-libgcj-multifile --enable-
languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --
disable-dssi --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
--with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.1 20060525 (Red Hat 4.1.1-1)

i run it on this program:
FILE: hello.c

//
// $ gcc -Wconversion -o hello hello.c
// $ hello
//

#include <stdio.h>
main()
{
unsigned long a_ulong = 0; // 32 bit
short a_short_array[128]; // 16 bit each

a_ulong = 1234567;

a_short_array[26] = a_ulong;

printf("%d, %hx, %x, %lx \n", sizeof(a_short_array),
a_short_array[26], a_short_array[26], a_ulong);
//
// printf output is:
//
// 256, d687, ffffd687, 12d687
//
}

and am using this invocation to compile:

$ gcc -Wconversion -o hello hello.c

which results in NO WARNINGS! even though it is clear that bits are
dropped in this line of code:

a_short_array[26] = a_ulong;

isn't there a way to get this thing to complain when i do an
assignment (without explicit casting) of a 32-bit int to a 16-bit
int? we know that bits can be potentially dumped in such an
assignment. why can't i get this thing to warn me? i've been to:

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options

and this seems to confirm what i think the compiler should do. i have
also tried -Wall .

please reply to both newsgroups as i don't always hang out at
comp.lang.c .

i hope someone can explain this.

thank you.

r b-j
 
D

Douglas A. Gwyn

robert said:
isn't there a way to get this thing to complain when i do an
assignment (without explicit casting) of a 32-bit int to a 16-bit
int? we know that bits can be potentially dumped in such an
assignment. why can't i get this thing to warn me?

That's a job for a tool like "lint". There are too many legitimate
cases where the potential problem is not an actual problem for the
compiler to routinely warn you about it. Perhaps in the huge gcc
"manual page" some warning option for this purpose is documented?
 
R

robert bristow-johnson

That's a job for a tool like "lint".

actually, i think not. this is a compiler issue when an implicit type
conversion (between different flavors of int) *may* cause a change of
value. when building a big project, if you want to impose a
discipline on a bunch of different programmers to not do sloppy
actions that might loose bits somewhere where you won't be looking
(because it is not apparent that any such values were changed in an
expressed equality), these *potential* problems should be flagged in
the build. then you can go into the code, examine it, and if you
think the conversion is kosher, put an explicit cast on it. then the
warning goes away.
There are too many legitimate
cases where the potential problem is not an actual problem for the
compiler to routinely warn you about it.

and for those legitimate cases where you are so confident that the
conversion is no problem, you can use an explicit cast (which
precludes a -Wconversion warning) or you can look at the warning
message at build time, ignore it, and run your code anyway.
Perhaps in the huge gcc
"manual page" some warning option for this purpose is documented?

it is. and i quoted it. and it says, with the -Wconversion flag set,
that implicit conversions that *may* change a value get flagged as a
warning. but in my simple test, it was clear that this conversion
that did just that, did not get even a warning.
 
D

Douglas A. Gwyn

robert bristow-johnson said:
actually, i think not. this is a compiler issue when an implicit type
conversion (between different flavors of int) *may* cause a change of
value. when building a big project, if you want to impose a
discipline on a bunch of different programmers to not do sloppy
actions that might loose bits somewhere where you won't be looking
(because it is not apparent that any such values were changed in an
expressed equality), these *potential* problems should be flagged in
the build. then you can go into the code, examine it, and if you
think the conversion is kosher, put an explicit cast on it. then the
warning goes away.

So you prefer to make more work for programmers who know
what they are doing, to supposedly protect those who don't?
The point about using a separate tool is that it avoids confusing
compilation with education.
 
O

Oli Charlesworth

So you prefer to make more work for programmers who know
what they are doing, to supposedly protect those who don't?

If the programmers knew what they were doing, they'd know that writing
good code in a team environment involves making it self-documenting.
Use of explicit casts, semantics such as "static" and "const", and not
relying on platform-dependent quirks are a few ways of achieving this
goal.

Although a lot of programmers think it's terribly clever to be able to
hold all the subtle gotchas about their code in their head, or make
liberal use of language quirks (I used to be one of these people),
it's not terribly productive when more than one person (themself) has
to read their code.

The point about using a separate tool is that it avoids confusing
compilation with education.

There's also the fact that "knows what they're doing" != "infallible".
If there's no explicit cast, there's no way of telling whether it was
intentional, or an oversight that will only display faulty behaviour
in edge cases.
 
R

Randy Yates

Douglas A. Gwyn said:
So you prefer to make more work for programmers who know
what they are doing, to supposedly protect those who don't?
The point about using a separate tool is that it avoids confusing
compilation with education.

If that's your philosophy, then why have any errors or warnings at all?

At what place do you draw the line and say, "This is education, this
is compiling."?

Even if you "stooped" to placing a warning in such situations, programmers
"who know what they're doing" can still override any warning message by
simply explicitly typecasting.
--
% Randy Yates % "Remember the good old 1980's, when
%% Fuquay-Varina, NC % things were so uncomplicated?"
%%% 919-577-9882 % 'Ticket To The Moon'
%%%% <[email protected]> % *Time*, Electric Light Orchestra
http://home.earthlink.net/~yatescr
 
R

robert bristow-johnson

So you prefer to make more work for programmers who know
what they are doing, to supposedly protect those who don't?
The point about using a separate tool is that it avoids confusing
compilation with education.

first of all, i think it should be an option. and the way that -
Wconversion was described in the manual i quoted, it appears that this
option actually existed in gcc, and i *know* this option existed (as a
check box) in CodeWarrior on the Mac, when i used it.

the extra word for programmers who know what they are doing is to used
explicit casts:

a_short = (short)a_long;

or

a_long = (long)an_unsigned_long;

typing in the explicit cast is not an undue burden to show the
compiler (and other people looking at your code) that you *mean* to
be making such an assignment that requires such a conversion that a
value might be changed. that's not a ridiculous requirement. it's
similar to requiring that all functions defined have prototypes, that
global variables be avoided whenever possible, that sensible naming
conventions and structured and modular programming (as opposed to
spagetti code) be encouraged, that APIs be defined and used.

requiring explicit type casting whenever there is an assignment from
one type to another, at least when such assignment can change a value,
lest an annoying warning is generated, seems hardly a bad thing to
expect from even the good programmers who know what they are doing.

spagetti code, where people play fast and loose with variant types,
use naming "conventions" where every variable is a one or two letter
name, and no comments, that is something that the programmers who know
what they, themselves, are doing but are too lazy to polish up so that
the code successfully communicates to other human readers, all this is
what i want to avoid in the routine case.

r b-j
 
R

robert bristow-johnson

So you prefer to make more work for programmers who know
what they are doing, to supposedly protect those who don't?

i fail to see any traction in that point. it's an option called -
Wconversion and the default is OFF. so if these "programmers who know
what they are doing" do not want to make more work for themselves,
they simply opt not to turn that option on.
The point about using a separate tool is that it avoids confusing
compilation with education.

no, it's not about education. i, for one, did not bring that issue
up. it's a warning at the compiler level that examines the *implicit*
conversions of known fundamental types (like short, long, unsigned
short, unsigned long, etc) (explicit casts are not warned about, we
can then assume that the "programmers .. know what they are doing"
when they say

a_short = (short)a_long;

it's when they say (using less illustrative variable names)

a_short = a_long;

or even

an_unsigned_short = a_short;
or
a_short = an_unsigned_short;

or even

an_unsigned_long = a_short;

where there is a possible change in the value in that assignment (even
if the number of bits had INcreased).

pray tell, what is so bad that when someone makes those assignments,
that they (or someone else reviewing their code for potential bugs)
have an option to get an automated warning that there was a potential
loss of information (or changing of value) in such an assignment (or
passing it to a prototyped function)? i don't get the objection.
what can possibly be wrong with it, particularly if exactly such an
optional warning (-Wconversion) is described in the gcc manual?

curiously,

r b-j
 
R

Richard Heathfield

Oli Charlesworth said:

If the programmers knew what they were doing, they'd know that writing
good code in a team environment involves making it self-documenting.
Use of explicit casts,

Yes, that can be self-documenting. Nine casts out of ten, the code says
"I was written by a bozo". Incidentally, "explicit cast" is a
tautology, since casts are explicit conversions.

There's also the fact that "knows what they're doing" != "infallible".
If there's no explicit cast, there's no way of telling whether it was
intentional,

If there /is/ an explicit cast, the chances are pretty fair that it's
hiding (but not fixing) a bug.

<snip>
 
D

Douglas A. Gwyn

robert bristow-johnson said:
pray tell, what is so bad that when someone makes those assignments,
that they (or someone else reviewing their code for potential bugs)
have an option to get an automated warning that there was a potential
loss of information (or changing of value) in such an assignment (or
passing it to a prototyped function)?

Try it on some large body of actual code.
There are *many* existing *uncast* instances of char <- int and vice versa,
99.9something% of which are safe even though int-to-char "may lose
information".
 
R

robert bristow-johnson

i've taken comp.lang.c.moderated off of the post list because i didn't
want moderator approval there to gate this post to the other
newsgroups.

Try it on some large body of actual code.

i'm working at a company where there are several projects and each
product has a pretty large body of code (a small amount is shared
between projects). i brought this issue up because of exactly that:
hidden loss of information (or "changing a value") in a large body of
code and there seems to be no way (despite the gcc manual says there's
a way) to have the option to flag these potential changing of values.
There are *many* existing *uncast* instances of char <- int and vice versa,

and i am saying that, especially if the manual says so with -
Wconversion, i should be able to (as an option that is not the
default; you may elect not to take that option) detect, upon
compilation, those instances. what's the problem with that?
99.9something% of which are safe even though int-to-char "may lose
information".

i totally agree. but it doesn't speak to the issue. there is nothing
wrong with following such a practice as:

char a_char_array[256];
int an_int;
...
a_char_array[46] = (char)an_int;

so what's wrong with *having*the*option* of requiring such explicit
casts when such conversions are necessary? you don't have to use such
an option and you're welcome to say:

a_char_array[46] = an_int;

but why, especially when the gcc manual says we have such an option,
must i have to wade through lines and lines of code detecting such
potential loss of information when such potential loss of information
can be flagged by the compiler as a warning?

r b-j
 
G

glen herrmannsfeldt

robert bristow-johnson wrote:

(snip)
so what's wrong with *having*the*option* of requiring such explicit
casts when such conversions are necessary? you don't have to use such
an option and you're welcome to say:
a_char_array[46] = an_int;
but why, especially when the gcc manual says we have such an option,
must i have to wade through lines and lines of code detecting such
potential loss of information when such potential loss of information
can be flagged by the compiler as a warning?

Because so much C code uses int to store character data.

Note that in C any integer type smaller than int is converted to
int before just about any operation. Even character constants
such as 'c' are of type int not of type char. (They are char
in C++, as I understand it.) It would be just about impossible
to use such an option without putting a cast on every expression.

Just like the California cancer warning, which results in putting
the warning on anything and everything just in case, such that the
warning isn't useful anymore.

The return value of getchar() is int, which it has to be to return
EOF in addition to all valid char values, but would then require a
cast.

a_char_array[46] = (char)'c'; /* 'c' is an int */

a_char_array[46] = (char)(a_char_array[47] + a_char_array[48]);

/* the sum of two char values is an int */

makes ugly and harder to debug C code.

-- glen
 
J

John Hadstate

and i am saying that, especially if the manual says so with -
Wconversion, i should be able to (as an option that is not the
default; you may elect not to take that option) detect, upon
compilation, those instances. what's the problem with that?

so what's wrong with *having*the*option* of requiring such explicit
casts when such conversions are necessary?

but why, especially when the gcc manual says we have such an option,
must i have to wade through lines and lines of code detecting such
potential loss of information when such potential loss of information
can be flagged by the compiler as a warning?

Robert,

I am in complete agreement with your position about the need for and
desireability of such a warning option. However, it looks like "-
Wconversion" may not be the option you're seeking. It appears that "-
Wconversion" may apply only to implicit conversions performed with
reference to a function prototype. I could not find a -W option that
looked like it might serve our purpose. From the gcc man page on my
system:

-Wconversion
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 pro-
motion.

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".
 
R

robert bristow-johnson

I am in complete agreement with your position about the need for and
desireability of such a warning option. However, it looks like
"-Wconversion" may not be the option you're seeking. It appears that
"-Wconversion" may apply only to implicit conversions performed with
reference to a function prototype. I could not find a -W option that
looked like it might serve our purpose. From the gcc man page on my
system:

-Wconversion
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.

yeah, that reads a little different from the on-line manual i found at
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options
..

to me, prototyping is nice to define what type an argument is getting
finally converted to, but it shouldn't make any difference. whether
an argument is getting sent to a prototyped routine or if it's in an
assignment statement, we should, at least, have the _option_ to be
warned about potential "changing of value" unless we don't want to
include that in the build.

r b-j
 

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,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top