Implementation-defined Behavior
The C and/or C++ standards define certain compiler behavior that is implementation defined.
Messages
All diagnostic messages issued by the compilers are reported through the Cray Linux Environment (CLE) message system. For information about messages issued by the compilers and for information about the Cray Linux Environment (CLE) message system, see Compiler Message System Use.
Environment
When argc and argv are used as parameters to the main function, the array members argv[0] through argv[argc-1] contain pointers to strings that are set by the command shell. The shell sets these arguments to the list of words on the command line used to invoke the compiler (the argument list). For further information about how the words in the argument list are formed, refer to the documentation on the shell being run.
A third parameter, char **envp, provides access to environment variables. The value of the parameter is a pointer to the first element of an array of null-terminated strings that matches the output of the env command. The array of pointers is terminated by a null pointer.
The compiler does not distinguish between interactive devices and other, noninteractive devices. The library, however, may determine that stdin, stdout, and stderr (cin, cout, and cerr in Cray C++) refer to interactive devices and buffer them accordingly.
Identifiers
The identifier (as defined by the standards) is merely a sequence of letters and digits. Specific uses of identifiers are called names.
The Cray C compiler treats the first 255 characters of a name as significant, regardless of whether it is an internal or external name. The case of names, including external names, is significant. In Cray C++, all characters of a name are significant.
Types
The table below summarizes Cray C and C++ types and the characteristics of each type. Representation is the number of bits used to represent an object of that type. Memory is the number of storage bits that an object of that type occupies.
In the Cray C and C++ compilers, size, in the context of the sizeof operator, refers to the size allocated to store the operand in memory; it does not refer to representation, as specified in the table. Thus, the sizeof operator will return a size that is equal to the value in the Memory column of the table divided by 8 (the number of bits in a byte).
| Type | Representation Size and Memory Storage Size (bits) |
|---|---|
| bool (C++) | 8 |
| _Bool (C) | 8 |
| char | 8 |
| wchar_t | 32 |
| short | 16 |
| int | 32 |
| long | 64 |
| long long | 64 |
| float | 32 |
| double | 64 |
| long double | 64 |
| float complex | 64 (each part is 32 bits) |
| double complex | 128 (each part is 64 bits) |
| long double complex | 128 (each part is 64 bits) |
| _float128 | 128 |
| _float128 complex | 256 (each part is 128 bits) |
| Pointers | 64 |
Characters
The full 8-bit ASCII code set can be used in source files. Characters not in the character set defined in the standard are permitted only within character constants, string literals, and comments. The -h [no]calchars option allows the use of the $ sign in identifier names. For more information about the -h [no]calchars option, see -h [no]calchars.
A character consists of 8 bits. Up to 8 characters can be packed into a 64-bit word. A plain char type (that is, one that is declared without a signed or unsigned keyword) is treated as a signed type.
| Character Count | Integer Value |
|---|---|
| 'a' | 0x61 |
| 'ab' | 0x6162 |
| Character Constant | Integer Value | Explanation |
|---|---|---|
| '\a' | 0x7 | Recognized as the ASCII BEL character |
| '\8' | 0x38 | Not recognized; ASCII value for 8 |
| '\[' | 0x5b | Not recognized; ASCII value for [ |
| '\c' | 0x63 | Not recognized; ASCII value for c |
Wide Characters
Wide characters are treated as signed 64-bit integer types. Wide character constants cannot contain more than one multibyte character. Multibyte characters in wide character constants and wide string literals are converted to wide characters in the compiler by calling the mbtowc() function. The current locale in effect at the time of compilation determines the method by which mbtowc() converts multibyte characters to wide characters, and the shift states required for the encoding of multibyte characters in the source code. If a wide character, as converted from a multibyte character or as specified by an escape sequence, cannot be represented in the extended execution character set, it is truncated.
Integers
All integral values are represented in a two's complement format. When an integer is converted to a shorter signed integer, and the value cannot be represented, the result is the truncated representation treated as a signed quantity. When an unsigned integer is converted to a signed integer of equal length, and the value cannot be represented, the result is the original representation treated as a signed quantity.
The bitwise operators (unary operator ~ and binary operators <<, >>, &, ^, and |) operate on signed integers in the same manner in which they operate on unsigned integers. The result of e1 >> e2, where e1 is a negative-valued signed integral value, is that e1 is right-shifted e2 bit positions; vacated bits are filled with 1s. This behavior can be modified by using the -h nosignedshifts option (see -h nosignedshifts). Bits higher than the sixth bit are not ignored.
The result of the / operator is the largest integer less than or equal to the algebraic quotient when either operand is negative and the result is a nonnegative value. If the result is a negative value, it is the smallest integer greater than or equal to the algebraic quotient. The / operator behaves the same way in C and C++ as in Fortran.
The sign of the result of the percent (%) operator is the sign of the first operand.
Integer overflow is ignored. Because some integer arithmetic uses the floating-point instructions, floating-point overflow can occur during integer operations. Division by 0 and all floating-point exceptions, if not detected as an error by the compiler, can cause a run time abort.
128-Bit Floating Point and 256-Bit Complex Predefined Types
The Cray C and C++ Compilers now support 128-bit floating point and 256-bit complex predefined types using the X86-64 ABI definitions for type names and data layout. These types are sometimes referred to as quad-precision. In C and C++, use __float128, and __float128 _complex. The header file quadmath.h defines the 128-bit functions and the header file complex.h defines the complex functions.
The base type itself uses 128 bits of storage with a guaranteed minimum alignment on a 128-bit boundary, little endian, has a 15-bit exponent, a 113-bit mantissa, and an exponent bias of 16383, and is compatible with the gcc implementation.
In C and C++, long double remains identical to double – 64-bit IEEE, and not 80-bit extended precision.
C forms of intrinsic math functions offer full support for quad-precision types. See the intro_quad_precision(3i) man page for a complete list of intrinsic functions that support quad-precision.
extern __float128 strtoflt128 (const char *, char **);
extern int quadmath_snprintf (char *str, size_t size, const char *format, ...)% cat printf128main.c printf128.f
#include <quadmath.h>
#include <math.h>
printf128_(__float128 *x);
void main(){
__float128 x=1.234567890123456789012345678901234567890Q;
printf128_(&x);
}
subroutine printf128(qx)
real*16 qx
print "('qx:', f5.1, e45.35)",qx,qx
end
%cc printf128main.c printf128.o && ./a.out
qx: 1.2 0.12345678901234567890123456789012346E+01Arrays and Pointers
An unsigned long value can hold the maximum size of an array. The type size_t is defined to be a typedef name for unsigned long in the headers: malloc.h, stddef.h, stdio.h, stdlib.h, string.h, and time.h. If more than one of these headers is included, only the first defines size_t.
A type long can hold the difference between two pointers to elements of the same array. The type ptrdiff_t is defined to be a typedef name for long in the header stddef.h.
static void **Table;
size_t offset = -BlockSize[nr];
Table = (void **) malloc(MAXBLOCKS * sizeof(void *));
Table[i] = (void **) (((long) Table[i]) + offset);Pointers on Cray Linux Environment (CLE) systems are byte pointers. Byte pointers use the same internal representation as integers; a byte pointer counts the numbers of bytes from the first address.
A pointer can be explicitly converted to any integral type large enough to hold it. The result will have the same bit pattern as the original pointer. Similarly, any value of integral type can be explicitly converted to a pointer. The resulting pointer will have the same bit pattern as the original integral type.
Registers
Use of the register storage class in the declaration of an object has no effect on whether the object is placed in a register. The compiler performs register assignment aggressively; that is, it automatically attempts to place as many variables as possible into registers.
Classes, Structures, Unions, Enumerations, and Bit Fields
Accessing a member of a union by using a member of a different type results in an attempt to interpret, without conversion, the representation of the value of the member as the representation of a value in the different type.
- For a member bit field of any size, alignment is any bit position that allows the member to fit entirely within a 64–bit word.
- For a member with a size less than 64 bits, alignment is the same as the size. For example, a char has a size and alignment of 8 bits; a float has a size and alignment of 32 bits.
- For a member with a size equal to or greater than 64 bits, alignment is 64 bits.
- For a member with array type, alignment is equal to the alignment of the element type.
A plain int type bit field is treated as a signed int bit field.
The values of an enumeration type are represented in the type signed int in C; they are a separate type in C++.
Qualifiers
When an object that has volatile-qualified type is accessed, it is simply a reference to the value of the object. If the value is not used, the reference need not result in a load of the value from memory.
Declarators
A maximum of 12 pointer, array, and/or function declarators are allowed to modify an arithmetic, structure, or union type.
Statements
The compiler has no fixed limit on the maximum number of case values allowed in a switch statement. The Cray C++ compiler parses asm statements for correct syntax, but otherwise ignores them.
Exceptions
In Cray C++, when an exception is thrown, the memory for the temporary copy of the exception being thrown is allocated on the stack and a pointer to the allocated space is returned.
System Function Calls
For a description of the form of the unsuccessful termination status that is returned from a call to exit(3), see the exit(3) man page.
Preprocessing
#if 'a' == 97
if ('a' == 97) The -I option and the method for locating included source files is described in -I incldir.#include directive must be a valid or Cray Linux Environment (CLE) file name or path name. An #include directive may specify a file name by means of a macro, provided the macro expands into a source file character sequence delimited by double quotes or < and > delimiters, as follows:
#define myheader "./myheader.h"
#include myheader
#define STDIO <stdio.h>
#include STDIO The macros __DATE__ and __TIME__ contain the date and time of the beginning of translation.