On Sat, 12 Aug 2006 21:25:56 GMT, Charles Sullivan
<cw******@triad .rr.comwrote in comp.lang.c:
I have a program written in C under Linux (gcc) which a user has
ported to run under AT&T SysV R4.
He sent me a copy of his makelog which displays a large number
of compiler warnings similar to this:
warning: semantics of ">>" change in ANSI C; use explicit cast
Prior to the adoption of the 1989/1990 ANSI/ISO standard, some
compilers applied different rules for promoting unsigned types.
The statement to which this applies is:
xuc = ((uc[7] & 0xF0 ) >4);
where the declarations for xuc and uc are:
extern unsigned char xuc;
unsigned char uc[20];
Assuming 8-bit characters, which is true of every Linux I have ever
heard of, then uc[7] has a value between 0 and 255 inclusive. Under
any ANSI/ISO version of C, this will cause uc[7] to be promoted to
signed int, since a signed int can hold all the values of an unsigned
char. This is called a "value preserving" promotion.
On the other hand, some pre-standard compilers performed what might be
called "unsigned preserving" promotions. Unsigned char promoted to
unsigned int and unsigned int promoted to unsigned long.
If the pre-standard C compiler for the AT&T implementation used the
old rules, the uc[7] would promote to an unsigned int with a value
between 0 and 255. This would cause a conversion of integer literal
0xF0 to unsigned int, and the bitwise and would be performed on the
two unsigned ints, producing an unsigned int result, which was finally
shifted right.
Under the new rules, uc[7] is promoted to a signed int with a value
between 0 and 255. Since the integer literal 0xF0 already has type
signed int, it is not converted and the bitwise and takes place on two
signed int values, generating a signed int result. This signed int
result is then shifted right.
There are potential surprises in right shifting signed ints (or signed
longs, for that matter) with negative values. It is
implementation-defined whether the sign bit is maintained or
discarded.
In this particular case, however, you will be right shifting a signed
int with a positive value, and this is absolutely well defined as long
as the shift count is within range, which is certainly is. Signed
integer types with a positive value are defined by the standard to
have identical bit representations as the corresponding unsigned types
with the same value, and right shifting yields the same result.
So due to the values used in this case, there is no actual possibility
of a different result on any implementation. With other values,
specifically those that involve right shifting a signed integer type
with a negative value, there could be a difference in the result. The
compiler is warning about the possibility in the abstract, not
checking to see whether it could happen with the specific values in
this particular case.
I assume this warning means his compiler expects the number
4 in that statement to be cast as an unsigned char, but I
That's a totally incorrect assumption. The type of the right operand,
the shift count, does not play any value at all in any promotion of
the left operand or the type of the result. If the type of the shift
count is less than int, it is promoted to either signed or unsigned
int, but the type on which the operation is performed, and the type of
the result, is based strictly on the promoted type of the left
operand.
haven't yet found a warning level switch in my gcc compiler
which displays this warning, so can't be sure. There's no
such warning for another statement in the same function:
xi = uc[8] + (uc[9] << 8);
where in this case:
extern int xi;
Is his compiler being overly picky or is the (apparently
expected) cast something that should be done in well-written
C code?
(Note: the variable names shown are simplified for clarity;
the actual names used are much more self-explanatory).
Thanks for your help.
The code is actually correct, well-defined, and fully portable. But
if you want to eliminate the warning, as Morris suggested, change the
type of the integer literal:
xuc = ((uc[7] & 0xF0u) >4);
This should eliminate it.
--
Jack Klein
Home:
http://JK-Technology.Com
FAQs for
comp.lang.c
http://c-faq.com/
comp.lang.c++
http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html