Silent Changes for ANSI C [ HP C Programmer's Guide ] MPE/iX 5.0 Documentation
HP C Programmer's Guide
Silent Changes for ANSI C
Non-ANSI mode HP C is different from ANSI mode HP C in ways that
generally go unnoticed. On HP-UX, many of these silent differences can
be found by running the lint(1) program. The following list provides
some of these silent changes:
* Trigraphs are new in ANSI C. A trigraph is a three character
sequence that is replaced by a corresponding single character.
For example, ??= is replaced by #. For more information on
trigraphs, refer to "Preprocessing Directives" in the HP C/HP-UX
Reference Manual or HP C/iX Reference Manual.
* Promotion rules for unsigned char and unsigned short have changed.
Non-ANSI mode rules specify when an unsigned char or unsigned
short is used with an integer the result is unsigned. ANSI mode
rules specify the result is signed. The following program example
illustrates a case where these rules differ:
main(){
unsigned short us = 1;
int i = -2;
printf("%s\n",(i+us)>0 ? "non-ANSI mode" : "ANSI mode");
}
Note that differences in promotion rules can occur under the
following conditions: (1)
_________________________________________________________________
FOOTNOTE (1) Rationale for Proposed American National Standard
for Information Systems - Programming Language C (311
First Street, N.W., Suite 500, Washington, DC
20001-2178; X3 Secretariat: Computer and Business
Equipment Manufacturers Association), pages 34-35
_________________________________________________________________
* An expression involving an unsigned char or unsigned short
produces an integer-wide result in which the sign bit is
set: that is, either a unary operation on such a type, or
a binary operation in which the other operand is int or a
"narrower" type.
* The result of the preceding expression is used in a context
in which its condition of being signed is significant: it
is the left operand of the right-shift operator or either
operand of /,%,<,<=,>, or >=.
* Floating-point expressions with float operands may be computed as
float precision in ANSI mode. In non-ANSI mode they will always
be computed in double precision.
* Initialization rules are different in some cases when braces are
omitted in an initialization.
* Unsuffixed integer constants may have different types. In
non-ANSI mode, unsuffixed constants have type int. In the ANSI
mode, unsuffixed constants less than or equal to 2147483647 have
type int. Constants larger than 2147483647 have type unsigned.
For example:
-2147483648
has type unsigned in the ANSI mode and int in non-ANSI mode. The
above constant is unsigned in the ANSI mode because 2147483648 is
unsigned, and the - is a unary operator.
* Empty tag declarations in a block scope create a new struct
instance in ANSI mode. The term block scope refers to identifiers
declared inside a block or list of parameter declarations in a
function definition that have meaning from their point of
declaration to the end of the block. In the ANSI mode, it is
possible to create recursive structures within an inner block.
For example:
struct x { int i; };
{ /* inner scope */
struct x;
struct y { struct x *xptr; };
struct x { struct y *yptr; };
}
In ANSI mode, the inner struct x declaration creates a new version
of the structure type which may then be referred to by struct y.
In non-ANSI mode, the struct x; declaration refers to the outer
structure.
* On Series 700/800, variable shifts (<< or >>) where the right
operand has a value greater than 31 or less than 0 will no longer
always have a result of 0. For example,
unsigned int i,j = 0xffffffff, k = 32;
i = j >> k; /* i gets the value 0 in compatibility mode, */
/* 0xffffffff(-1) in ANSI mode. */
MPE/iX 5.0 Documentation