#3794: Complier warnings on OS X 10.11.1 with Xcode 7.1.1
---------------------+---------------------
Reporter: chdiza | Owner: brendan
Type: defect | Status: new
Priority: minor | Milestone:
Component: SMTP | Version:
Resolution: | Keywords:
---------------------+---------------------
Comment (by code@…):
{{{
In regards to Comment #3, pertainting to the original code snippet:
while(a && *a > 0 && *a < 128)
"Some quick Googling seems to say that whether "char *" is signed or
unsigned is implementation dependent."
The problem has nothing to do with the value of char * (i.e. the value
of the variable a). The problem is the value of *a, i.e. the type of
data that a points to, which is char. A char is signed on every
platform. This is not a harmless warning, IT IS A BUG. This is
illustrated by the following tiny program:
#include <stdio.h>
int main(int argc, char **argv)
{
char x;
x = 128;
printf("%d\n", (int)x);
return 0;
}
On any sane platform, this will print -128, not 128. That's because
the value of x is, in fact, -128; the compiler has performed an
implicit cast (I personally would like to see a warning here--this is
a hard-to-spot bug, unless you really intended for x to be -128, in
which case you should have written it that way).
The general gist of the problem is that char is technically a
(SIGNED!) numeric data type, but is most commonly used to contain
character data in ASCII encoding. Character data is inherently
unsigned, i.e. ASCII code 128 is not a signed value, however the value
of a signed char with the equivalent bits set is -128. So if you're
going to compare character data to its unsigned ASCII code, your data
type needs to either be unsigned inherently (unsigned char) or you
need to cast it to unsigned data when you do your comparison.
Vincent's proposed fix is technically correct, but is pretty
unreadable, possibly obscuring the intent to the reader. A better fix
that retains the intent would have been (almost) what Petr suggested,
except he had the sign wrong, and there's no longer any reason to
compare to 0, since unsigned chars can never be negative:
while (a && *((unsigned char *)a) < 128)
However, if you're going to be comparing chars to numeric literal
ASCII codes, you should really consider whether the data should
actually be unsigned char instead of just char. The main reason NOT
to do that is if you have to use it with old POSIX API calls that got
the sign wrong, expectng a signed char* rather than an unsigned char*,
of which there are a number (like strcmp() et al.). In that case,
you'll end up doing far more casting with the "right" signedness than
without, so just cast the uncommon case.
}}}
--
Ticket URL: <http://dev.mutt.org/trac/ticket/3794#comment:11>
Mutt <http://www.mutt.org/>
The Mutt mail user agent