[an error occurred while processing this directive]

HP OpenVMS Systems

C Programming Language
Content starts here Compaq C

Compaq C
Language Reference Manual


Previous Contents Index

1.9 Constants

There are four categories of constants in C:

  • Integer constants (such as 63 , 0 , and 42L )
  • Floating-point constants (such as 1.2 , 0.00 , and 77E+2 )
  • Hexadecimal floating-point constants (such as 0x1P-1 or 0x.1P3 to represent 1/2).
  • Character constants (such as 'A' , '0' , and L'\n' )
  • Enumeration constants (such as enum boolean { NO, YES }; ), where NO and YES are the enumeration constants

The following sections describe these constants.

The value of any constant must be within the range of representable values for the specified type. Regardless of its type, a constant is a literal or symbolic value that does not change. A constant is also an rvalue, as defined in Section 2.14.

1.9.1 Integer Constants

Integer constants are used to represent whole numbers. An integer constant can be specified in decimal, octal, or hexadecimal radix, and can optionally include a prefix that specifies its radix and a suffix that specifies its type. An integer constant cannot include a period or an exponent part.

Follow these rules when specifying an integer constant:

  • To specify a decimal integer constant, use a sequence of decimal digits in which the first digit is not 0. The value of a decimal constant is computed in base 10.
  • To specify an octal integer constant, start the sequence with a zero (0) and follow the 0 (if necessary) with a sequence composed of the digits 0 to 7. A leading 0 alone signifies the octal number 0. The value of an octal constant is computed in base 8.
  • To specify a hexadecimal integer constant, start the hexadecimal sequence with a 0 followed by the character X (or x ). Follow the X or x with one or more hexadecimal characters (the digits 0 to 9 and the upper or lowercase letters A to F). The value of a hexadecimal constant is computed in base 16 (the letters A to F have the values 10 to 15, respectively).

Without explicit specification, the type of an integer constant defaults to the smallest possible type that can hold the constant's value, unless the value is suffixed with an L , l , LL ( (ALPHA ONLY)), ll ( (ALPHA ONLY)), U , or u .

The C99 standard introduced the type long long int (both signed and unsigned) as a standard integer type whose range of values requires at least 64 bits to represent. Although Compaq C on Alpha systems implemented the type long long as a language extension many releases ago, the compiler followed the C89 rules for determining the type of an integer constant. Those rules specified that an unsuffixed decimal integer with a value too large to be represented in a signed long would be given the type unsigned long if it would fit, and only be given a long long type if the value was too large for unsigned long . (Note: The long long data type is supported on Alpha systems only.)

In standardizing the long long type, the C99 standard regularized these rules and made them extensible to longer types. In particular, unsuffixed decimal integer constants are given the smallest signed integer type that will hold the value (the minimum type is still int ). If the value is larger than the largest value of signed long long , it is given the next larger implementation-defined signed integer type (if there is one). Otherwise C99 states that the behavior is undefined. Compaq C, however, uses the type unsigned long long next. The only portable way to specify a decimal constant that will be given an unsigned type is to use a suffix containing u or U .

Compaq C continues to use the C89 rules in VAXC, COMMON, and strict ANSI89 modes (including MIA), but uses the new C99 rules in all other modes. Table 1-5 shows the rules for determining the type of an integer constant. The type of an integer constant is the first of the corresponding list in which its value can be represented.

Table 1-5 Rules for Assigning Type to Integer Constants
Suffix Decimal Constant Octal or Hexadecimal Constant
none int int
  long int unsigned int
  long long int 1 long int
  unsigned long long int unsigned long int
    long long int
    unsigned long long int
     
u or U unsigned int unsigned int
  unsigned long int unsigned long int
  unsigned long long int unsigned long long int
     
l or L long int long int
  long long int 1 unsigned long int
  unsigned long long int long long int
    unsigned long long int
     
Both u or U unsigned long int unsigned long int
and l or L unsigned long long int unsigned long long int
     
ll or LL long long int long long int
  unsigned long long int unsigned long long int
     
Both u or U unsigned long long int unsigned long long int
and ll or LL    

1In VAXC, COMMON, ANSI89, and MIA modes, the type unsigned long int is assigned before long long int.

For example, the constant 59 is assigned the int data type; the constant 59L is assigned the long data type; the constant 59UL is assigned the unsigned long int data type.

Integer constant values are always nonnegative; a preceding minus sign is interpreted as a unary operator, not as part of the constant. If the value exceeds the largest representable integer value (causing an overflow), the compiler issues a warning message and uses the greatest representable value for the integer type. Unsuffixed integer constants can have different types, because without explicit specification the constant is represented in the smallest possible integer type.

Note

The new C99 rules for determining the type of an integer constant could lead to some constants in your program being interpreted as having a signed type when previous compiler versions gave them an unsigned type. This could affect your program's behavior in subtle ways. The new message intconstsigned can be enabled to report constants in your source code that are being treated differently under the C99 rules than they were in previous releases. This message is also part of the new message group NEWC99. If your program relied on unsigned treatment, the simple fix is to add the correct suffix including a "U" or "u" to force the constant to have the expected type. Such a change would be backward compatible and portable.

1.9.2 Floating-Point Constants

A floating-point constant has a significand part that may be followed by an exponential part and an optional suffix that specifies its type (for example, 32.45E2 ).

The components of the significand part may include a digit sequence representing the whole number part, followed by a period (.), followed by a digit sequence representing the fractional part.

The components of the exponent part are an e, E, p, or P followed by an exponent consisting of an optionally signed digit sequence.

Either the whole-number part or the fraction part of the significand must be present. For decimal floating constants, either the period or the exponent part must be present.

1.9.2.1 Semantics

The significand part of a floating-point constant is interpreted as a decimal or hexadecimal rational number; the digit sequence in the exponent is interpreted as a decimal integer. For decimal floating constants, the exponent indicates the power of 10 by which the significand part is to be scaled. For hexadecimal floating constants, the exponent indicates the power of 2 by which the significand part is to be scaled. For decimal floating constants, and for hexadecimal floating constants when FLT_RADIX is not a power of 2, the result is either the nearest representable value, or the larger or smaller representable value immediately adjacent to the nearest representable value, chosen in an platform-dependent manner. For hexadecimal floating constants when FLT_RADIX is a power of 2, the result is correctly rounded.

Floating-point constant values must be nonnegative; a preceding minus sign is interpreted as a unary operator, not as part of the constant.

1.9.2.2 Floating-Point Type

Floating-point constants have the following type:

  • An unsuffixed floating-point constant has type double .
    If the value exceeds the largest value representable by type double , a compiler overflow warning results. (The result is truncated within the double type.)
  • If suffixed by the letter f or F, it has type float .
  • If suffixed by the letter l or L, it has type long double .

1.9.2.3 Hexadecimal Floating-Point Constants

A word about hexadecimal floating-point constants... The C99 standard introduced a hexadecimal form of floating-point constants. This form of constant permits floating-point values to be specified reliably to the last bit of precision. It does not specify a bit pattern for the representation. Instead it is interpreted much like an ordinary decimal floating-point constant except that the significand is written in hexadecimal radix, and the exponent is expressed as a decimal integer indicating the power of two by which to multiply the significand. A "P" instead of an "E" separates the exponent from the significand. Thus, for example, 1/2 can be written as either 0x1P-1 or 0x.1P3.

The C99 standard also adds printf / scanf specifiers for this form of value, but that support will be in OpenVMS run-time libraries after OpenVMS Version 7.3.

1.9.2.4 Examples

Table 1-6 shows examples of valid notational options.

Table 1-6 Floating-Point Notation
Notation Value Type
.0 0.000000 double
0. 0.000000 double
2. 2.000000 double
2.5 2.500000 double
2e1 20.00000 double
2E1 20.00000 double
0x1P-1 0.500000 double
0x.1P3 0.500000 double
2.E+1 20.00000 double
2e+1 20.00000 double
2e-1 0.200000 double
2.5e4 25000.00 double
2.5E+4 25000.00 double
2.5F 2.500000 float
2.5L 2.500000 long double

1.9.3 Character Constants

A character constant is any character from the source character set enclosed in apostrophes. Character constants are represented by objects of type int . For example:


char alpha = 'A';

Characters such as the new-line character, single quotation marks, double quotation marks, and backslash can be included in a character constant by using escape sequences as described in Section 1.9.3.3. All valid characters can also be included in a constant by using numeric escape sequences, as described in Section 1.9.3.4.

The value of a character constant containing a single character is the numeric value of the character in the current character set. Character constants containing multiple characters within the single quotation marks have a value determined by the compiler. The value of a character constant represented by an octal or hexadecimal escape sequence is the same as the octal or hexadecimal value of the escape sequence. The value of a wide character constant (discussed in Section 1.9.3.1) is determined by the mbtowc library function.

There is a limit of four characters for any one character constant. Enclosing more than four characters in single quotation marks (such as 'ABCDE' ), generates an overflow warning.

Note that the byte ordering of character constants is platform specific.

1.9.3.1 Wide Characters

C provides for an extended character set through the use of wide characters. Wide characters are characters too large to fit in the char type. The wchar_t type is typically used to represent a character constant in a character set requiring more than 256 possible characters, because 8 bits can represent only 256 different values.

A character constant in the extended character set is written using a preceding L , and is called a wide-character constant. Wide-character constants have an integer type, wchar_t , defined in the <stddef.h> header file. Wide-character constants can be represented with octal or hexadecimal character escape sequences, just like normal character escape sequences, but with the preceding L .

Strings composed of wide characters can also be formed. The compiler allocates storage as if the string were an array of type wchar_t , and appends a wide null character (\0) to the end of the string. The array is just long enough to hold the characters in the string and the wide null character, and is initialized with the specified characters.

The following examples show valid wide-character constants and string literals:


wchar_t wc = L'A';
wchar_t wmc = L'ABCD';
wchar_t *wstring = L"Hello!";
wchar_t *x = L"Wide";
wchar_t z[] = L"wide string";

Compaq C stores wchar_t objects as unsigned long objects (OPENVMS) or unsigned int objects (TRU64 UNIX) in 32 bits of storage. The null character at the end of a wide-character string is 32 bits long.

1.9.3.2 Multibyte Characters

Some programmers requiring an extended character set have used shift-dependent encoding schemes to represent the non-ASCII characters in the normal char size of 8 bits. This encoding results in multibyte characters. ANSI C supports these encoding schemes, in addition to providing the wide-character type wchar_t .

In accordance with the ANSI standard, Compaq C recognizes multibyte characters in the following contexts:

  • Comments
  • String literals
  • Header names
  • Character constants

For proper input and output of the multibyte character encodings, and to prevent conflicts with existing string processing routines, note the following rules governing the use of multibyte characters:

  • A byte with all bits set to zero is always recognized as a null character. Null characters can only be single bytes.
  • A null character cannot occur as the second or subsequent byte of a multibyte character.

Transforming multibyte characters to wide-character constants and wide string literals eases the programmer's problems when dealing with shift-state encoding. There are several C library functions available for transforming multibyte characters to wide characters and back. See Chapter 9 for more information.

1.9.3.3 Character Escape Sequences

Characters that cannot be displayed on a standard terminal, or that have special meaning when used in character constants or string literals, can be entered as source characters by entering them as character escape sequences. A backslash (\) begins each character escape sequence. Each of the escape sequences is stored in a single char or wchar_t object. Table 1-7 lists the ANSI-defined escape sequences.

Table 1-7 Character Escape Sequences
Character Escape Sequence
Alert (Bell) \a
Backspace \b
Form Feed \f
New line \n
Carriage Return \r
Horizontal Tab \t
Vertical Tab \v
Backslash \\
Single Quote \'
Double Quote \"
Question Mark \?

No other character escape sequences are valid. If another sequence is encountered in the source code, the compiler issues a warning and the backslash character is ignored.

An example of a character escape sequence use follows:


printf ("\t\aReady\?\n");

Upon execution, this results in an alert bell and the following prompt:


     Ready?


Previous Next Contents Index