JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Oracle Solaris Studio 12.3: C User's Guide     Oracle Solaris Studio 12.3 Information Library
search filter icon
search icon

Document Information


1.  Introduction to the C Compiler

2.  C-Compiler Implementation-Specific Information

3.  Parallelizing C Code

4.  lint Source Code Checker

5.  Type-Based Alias Analysis

6.  Transitioning to ISO C

6.1 Basic Modes

6.1.1 -Xc

6.1.2 -Xa

6.1.3 -Xt

6.1.4 -Xs

6.2 New-Style Function Prototypes

6.2.1 Writing New Code

6.2.2 Updating Existing Code

6.2.3 Mixing Considerations

6.3 Functions With Varying Arguments

6.4 Promotions: Unsigned Versus Value Preserving

6.4.1 Some Background History

6.4.2 Compilation Behavior

6.4.3 Example: The Use of a Cast

6.4.4 Example: Same Result, No Warning

6.4.5 Integral Constants

6.4.6 Example: Integral Constants

6.5 Tokenization and Preprocessing

6.5.1 ISO C Translation Phases

6.5.2 Old C Translation Phases

6.5.3 Logical Source Lines

6.5.4 Macro Replacement

6.5.5 Using Strings

6.5.6 Token Pasting

6.6 const and volatile

6.6.1 Types for lvalue Only

6.6.2 Type Qualifiers in Derived Types

6.6.3 const Means readonly

6.6.4 Examples of const Usage

6.6.5 Examples of volatile Usage

6.7 Multibyte Characters and Wide Characters

6.7.1 Asian Languages Require Multibyte Characters

6.7.2 Encoding Variations

6.7.3 Wide Characters

6.7.4 C Language Features

6.8 Standard Headers and Reserved Names

6.8.1 Standard Headers

6.8.2 Names Reserved for Implementation Use

6.8.3 Names Reserved for Expansion

6.8.4 Names Safe to Use

6.9 Internationalization

6.9.1 Locales

6.9.2 setlocale() Function

6.9.3 Changed Functions

6.9.4 New Functions

6.10 Grouping and Evaluation in Expressions

6.10.1 Expression Definitions

6.10.2 K&R C Rearrangement License

6.10.3 ISO C Rules

6.10.4 Parentheses Usage

6.10.5 The As If Rule

6.11 Incomplete Types

6.11.1 Types

6.11.2 Completing Incomplete Types

6.11.3 Declarations

6.11.4 Expressions

6.11.5 Justification

6.11.6 Examples: Incomplete Types

6.12 Compatible and Composite Types

6.12.1 Multiple Declarations

6.12.2 Separate Compilation Compatibility

6.12.3 Single Compilation Compatibility

6.12.4 Compatible Pointer Types

6.12.5 Compatible Array Types

6.12.6 Compatible Function Types

6.12.7 Special Cases

6.12.8 Composite Types

7.  Converting Applications for a 64-Bit Environment

8.  cscope: Interactively Examining a C Program

A.  Compiler Options Grouped by Functionality

B.  C Compiler Options Reference

C.  Implementation-Defined ISO/IEC C99 Behavior

D.  Features of C99

E.  Implementation-Defined ISO/IEC C90 Behavior

F.  ISO C Data Representations

G.  Performance Tuning

H.  Oracle Solaris Studio C: Differences Between K&R C and ISO C


6.4 Promotions: Unsigned Versus Value Preserving

The following information appears in the Rationale section that accompanies the 1990 ISO C Standard: “QUIET CHANGE”. A program that depends on unsigned preserving arithmetic conversions will behave differently, probably without complaint. This change is considered to be the most serious made by the Committee to a widespread current practice.

This section explores how this change affects our code.

6.4.1 Some Background History

In the first edition of The C Programming Language, unsigned specified exactly one type, with no unsigned chars, unsigned shorts, or unsigned longs. Most C compilers added these these very soon thereafter. Some compilers did not implement unsigned long but included the other two. Naturally, implementations chose different rules for type promotions when these new types mixed with others in expressions.

In most C compilers, the simpler rule unsigned preserving is used. When an unsigned type needs to be widened, it is widened to an unsigned type; when an unsigned type mixes with a signed type, the result is an unsigned type.

The other rule, specified by ISO C, is known as value preserving. in which the result type depends on the relative sizes of the operand types. When an unsigned char or unsigned short is widened, the result type is int if an int is large enough to represent all the values of the smaller type. Otherwise, the result type is unsigned int. The value preserving rule produces fewer unexpected arithmetic results for most expressions.

6.4.2 Compilation Behavior

Only in the transition or ISO modes (-Xt or -Xs) does the ISO C compiler use the unsigned preserving promotions. In the other two modes, conforming (–Xc) and ISO (–Xa), the value preserving promotion rules are used.

6.4.3 Example: The Use of a Cast

In the following code, assume that an unsigned char is smaller than an int.

int f(void)
    int i = -2;
    unsigned char uc = 1;

   return (i + uc) < 17;

The code causes the compiler to issue the following warning when you use the -xtransition option:

line 6: warning: semantics of "<" change in ISO C; use explicit cast

The result of the addition has type int (value preserving) or unsigned int (unsigned preserving), but the bit pattern does not change between these two. On a two’s-complement machine:

    i:       111...110 (-2)
+   uc:      000...001 ( 1)
        111...111 (-1 or UINT_MAX)

This bit representation corresponds to -1 for int and UINT_MAX for unsigned int. Thus, if the result has type int, a signed comparison is used and the less-than test is true. If the result has type unsigned int, an unsigned comparison is used and the less-than test is false.

The addition of a cast serves to specify which of the two behaviors is desired:

value preserving:
    (i + (int)uc) < 17
unsigned preserving:
    (i + (unsigned int)uc) < 17

Because differing compilers chose different meanings for the same code, this expression can be ambiguous. The addition of a cast is as much to help the reader as it is to eliminate the warning message.

The same situation applies to the promotion of bit-field values. In ISO C, if the number of bits in an int or unsigned int bit-field is less than the number of bits in an int, the promoted type is int; otherwise, the promoted type is unsigned int. In most older C compilers, the promoted type is unsigned int for explicitly unsigned bit-fields, and int otherwise.

Similar use of casts can eliminate situations that are ambiguous.

6.4.4 Example: Same Result, No Warning

In the following code, assume that both unsigned short and unsigned char are narrower than int.

int f(void)
    unsigned short us;
    unsigned char uc;
    return uc < us;

In this example, both automatics are either promoted to int or to unsigned int, so the comparison is sometimes unsigned and sometimes signed. However, the C compiler does not warn you because the result is the same for the two choices.

6.4.5 Integral Constants

As with expressions, the rules for the types of certain integral constants have changed. In K&R C, an unsuffixed decimal constant had type int only if its value fit in an int. An unsuffixed octal or hexadecimal constant had type int only if its value fit in an unsigned int. Otherwise, an integral constant had type long. At times, the value did not fit in the resulting type. In the 1990 ISO/IEC C standard, the constant type is the first type encountered in the following list that corresponds to the value:

When you use the -xtransition option,the ISO C compiler warns you about any expression whose behavior might change according to the typing rules of the constants involved. The old integral constant typing rules are used only in the transition mode. The ISO and conforming modes use the new rules.

Note - The rules for typing unsuffixed decimal constants has changed in accordance with the 1999 ISO C standard. See 2.1.1 Integral Constants .

6.4.6 Example: Integral Constants

In the following code, assume ints are 16 bits.

int f(void)
    int i = 0;

    return i > 0xffff;

Because the hexadecimal constant’s type is either int (with a value of– 1 on a two’s-complement machine) or an unsigned int (with a value of 65535), the comparison is true in– Xs and -Xt modes, and false in– Xa and– Xc modes.

Again, an appropriate cast clarifies the code and suppresses a warning:

-Xt, -Xs modes:
    i > (int)0xffff

-Xa, -Xc modes:
    i > (unsigned int)0xffff
    i > 0xffffU

The U suffix character is a new feature of ISO C and probably produces an error message with older compilers.