Language Reference: IBM XL C Enterprise Edition V8.0 For AIX
Language Reference: IBM XL C Enterprise Edition V8.0 For AIX
Language Reference: IBM XL C Enterprise Edition V8.0 For AIX
0 for AIX
Language Reference
SC09-8004-00
Language Reference
SC09-8004-00
Note! Before using this information and the product it supports, be sure to read the general information under Notices on page 205.
First Edition (October, 2005) This edition applies to Version 8.0 of IBM XL C Enterprise Edition for AIX (product number 5724-I11) and to all subsequent releases and modifications until otherwise indicated in new editions. IBM welcomes your comments. You can send them by the Internet to the following address: [email protected] Include the title and order number of this book, and the page number or topic related to your comment. Be sure to include your e-mail address if you want a reply. When you send information to IBM, you grant IBM a nonexclusive right to use or distribute the information in any way it believes appropriate without incurring any obligation to you. Copyright International Business Machines Corporation 1998, 2005. All rights reserved. US Government Users Restricted Rights Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
Contents
About this document . . . . . . . . vii
Who should read this document . . . . . . . vii Supported language standards . . . . . . . . vii Other standards and specifications . . . . . vii Language levels and language extensions . . . . viii Extensions related to GNU C . . . . . . . viii Extensions supporting the AltiVec Programming Interface . . . . . . . . . . . . . . viii How to use this document . . . . . . . . . ix How this document is organized . . . . . . . ix Conventions used in this document . . . . . . ix Typographical conventions . . . . . . . . ix Qualifying elements (icons and bracket separators) x How to read syntax diagrams . . . . . . . x Examples . . . . . . . . . . . . . . xii Related information . . . . . . . . . . . xii IBM XL C publications . . . . . . . . . xii Additional documentation . . . . . . . . xiii Related publications . . . . . . . . . . xiii Technical support . . . . . . . . . . . . xiii How to send your comments . . . . . . . . xiv The auto storage class specifier . . . . . . The static storage class specifier . . . . . The extern storage class specifier . . . . . The register storage class specifier . . . . . Type specifiers . . . . . . . . . . . . Integral types . . . . . . . . . . . . Boolean types . . . . . . . . . . . Floating-point types . . . . . . . . . Character types . . . . . . . . . . . The void type . . . . . . . . . . . Compatibility of arithmetic types (C only) . . Vector types . . . . . . . . . . . . User-defined types . . . . . . . . . . . Structures and unions . . . . . . . . . Enumerations . . . . . . . . . . . . Compatibility of structures, unions, and enumerations (C only) . . . . . . . . . typedef definitions . . . . . . . . . . Type qualifiers . . . . . . . . . . . . The const type qualifier . . . . . . . . The volatile type qualifier . . . . . . . The restrict type qualifier . . . . . . . . The __align qualifier . . . . . . . . . Type attributes . . . . . . . . . . . . The aligned type attribute . . . . . . . The packed type attribute . . . . . . . The transparent_union type attribute (C only) . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 36 37 37 39 39 40 41 41 42 42 43 44 44 51 53 54 56 57 57 58 59 61 62 62 63
Chapter 4. Declarators . . . . . . . . 65
Overview of declarators . . . . . . . Examples of declarators . . . . . . Type names . . . . . . . . . . . Pointers . . . . . . . . . . . . Pointer arithmetic . . . . . . . . Type-based aliasing . . . . . . . . Compatibility of pointers (C only) . . . Arrays . . . . . . . . . . . . . Variable length arrays . . . . . . . Compatibility of arrays . . . . . . Initializers . . . . . . . . . . . . Initialization and storage classes . . . Designated initializers for aggregate types only) . . . . . . . . . . . . Initialization of vectors . . . . . . Initialization of structures and unions . Initialization of enumerations . . . . Initialization of pointers . . . . . . Initialization of arrays . . . . . . . Variable attributes . . . . . . . . . The aligned variable attribute . . . . The packed variable attribute . . . . The mode variable attribute . . . . . The weak variable attribute . . . . . . . . . . . . . . . . . (C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 66 66 68 68 69 70 70 72 73 73 74 75 77 78 80 80 81 83 85 86 86 86
. . . .
31 31 33 35
Arithmetic conversions and promotions . Integral conversions . . . . . . Boolean conversions . . . . . . Floating-point conversions . . . . Integral and floating-point promotions Lvalue-to-rvalue conversions . . . . Pointer conversions . . . . . . . . Conversion to void* . . . . . . Function argument conversions . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
89 89 90 90 91 92 92 93 93
. 126
Chapter 7. Statements
. . . . . . . 131
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 132 132 133 133 133 134 135 135 136 140 140 141 142 143 144 144 145 147 148 149 150 151
95
. 95 . 97 . 97 . 97 . 98 . 98 . 99 . 99 . . 100 . . 101 . . 101 . . 102 . . 102 . . 103 . . 104 . . 104 . . 104 . . 105 . . 105 . . 105 . . 106 . . 107 . . 108 . . 109 . . 110 . . 110 . . 111 . . 111 . . 112 . . 113 . . 113 . . 114 . . 114 . . 114 . . 115 . . 115 . . 116 . . 117 . . 118 . . 118 . . 119 . . 119 . . 120 . . 121 . . 121 . . 122 . . 123 . . 123 . . 124 . . 125
Labeled statements . . . . . . . . . Locally declared labels . . . . . . . Labels as values . . . . . . . . . Expression statements . . . . . . . . Block statements . . . . . . . . . . Example of blocks . . . . . . . . . Statement expressions . . . . . . . Selection statements . . . . . . . . . The if statement . . . . . . . . . The switch statement . . . . . . . . Iteration statements . . . . . . . . . The while statement . . . . . . . . The do statement . . . . . . . . . The for statement . . . . . . . . . Jump statements . . . . . . . . . . The break statement . . . . . . . . The continue statement . . . . . . . The return statement . . . . . . . . The goto statement . . . . . . . . Null statement . . . . . . . . . . . Inline assembly statements . . . . . . . Examples of inline assembly statements . Restrictions on inline assembly statements .
iv
XL C Language Reference
171
. . . . . . . . . . . . . . . . . . . . . 171 172 176 177 178 178 179 180 181 181 182 183 183 184 184 185 185 186 186 187 188
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
Appendix B. Vector data types and literals . . . . . . . . . . . . . . 197 Index . . . . . . . . . . . . . . . 199 Notices . . . . . . . . . . . . . . 205
Programming interface information . Trademarks and service marks . . Industry standards . . . . . . . . . . . . . . . . . . . 206 . 207 . 207
Contents
vi
XL C Language Reference
vii
v AltiVec Technology Programming Interface Manual, Motorola Inc. This specification for vector data types, to support VMX technology, is available at http://www.freescale.com/files/32bit/doc/ref_manual/ALTIVECPIM.pdf
viii
XL C Language Reference
Interface is also provided in Appendix A, The IBM XL C language extensions, on page 191. A complete list of vector data types and literals is provided in Appendix B, Vector data types and literals, on page 197.
Typographical conventions
The following table explains the typographical conventions used in this document.
Table 1. Typographical conventions Typeface bold Indicates Commands, executable names, compiler options and pragma directives. Parameters or variables whose actual names or values are to be supplied by the user. Italics are also used to introduce new terms. Example You can also use the #pragma comment directive to place comments into an object module. The attribute name can be specified with or without leading and trailing double underscore characters.
italics
ix
Programming keywords and Case and default label statements only library functions, compiler built-in appear in switch statements. functions, file and directory names, examples of program code, command strings, or user-defined names.
Meaning The text describes a feature that is an IBM XL C compiler extension to the standard language specifications.
v If you can choose from two or more items, they are shown vertically, in a stack. If you must choose one of the items, one item of the stack is shown on the main path.
keyword required_choice1 required_choice2
If choosing one of the items is optional, the entire stack is shown below the main path.
XL C Language Reference
The item that is the default is shown above the main path.
default_item alternate_item
keyword
v An arrow returning to the left above the main line indicates an item that can be repeated.
keyword
repeatable_item
A repeat arrow above a stack indicates that you can make more than one choice from the stacked items, or repeat a single choice. v Keywords are shown in nonitalic letters and should be entered exactly as shown (for example, extern). Variables are shown in italicized lowercase letters (for example, identifier). They represent user-supplied names or values. v If punctuation marks, parentheses, arithmetic operators, or other such symbols are shown, you must enter them as part of the syntax. The following syntax diagram example shows the syntax for the #pragma comment directive.
1 2 3 4 5 6 9 10 #pragmacomment(compiler) +date+ +timestamp+ ++copyright+++ | | | | +user+ +,"characters"+ 7 8
1 This is the start of the syntax diagram. 2 The symbol # must appear first. 3 The keyword pragma must appear following the # symbol. 4 The name of the pragma comment must appear following the keyword pragma. 5 An opening parenthesis must be present. 6 The comment type must be entered only as one of the types indicated: compiler, date, timestamp, copyright, or user. 7 A comma must appear between the comment type copyright or user, and an optional character string. 8 A character string must follow the comma. The character string must be enclosed in double quotation marks. 9 A closing parenthesis is required.
About this document
xi
10 This is the end of the syntax diagram. The following examples of the #pragma comment directive are syntactically correct according to the diagram shown above:
#pragma comment(date) #pragma comment(user) #pragma comment(copyright,"This text will appear in the module")
Examples
The examples in this document, except where otherwise noted, are coded in a simple style that does not try to conserve storage, check for errors, achieve fast performance, or demonstrate all possible methods to achieve a specific result.
xii
XL C Language Reference
Table 3. XL C PDF files (continued) Document title IBM XL C Enterprise Edition V8.0 for AIX Getting Started Guide, SC09-8003-00 IBM XL C Enterprise Edition V8.0 for AIX Compiler Reference, SC09-8001-00 IBM XL C Enterprise Edition V8.0 for AIX Programming Guide, SC09-8002-00 PDF file name getstart.pdf Description Contains an introduction to the XL C product, with information on setting up and configuring your environment, compiling and linking programs, and troubleshooting compilation errors. Contains information about the various compiler options, pragmas, macros, environment variables, and built-in functions, including those used for parallel processing.
compiler.pdf
proguide.pdf Contains information on advanced programming topics, such as application porting, interlanguage calls with Fortran code, library development, application optimization and parallelization, and the XL C high-performance libraries.
These PDF files are viewable and printable from Adobe Reader. If you do not have the Adobe Reader installed, you can download it from www.adobe.com.
Additional documentation
More documentation related to XL C, including redbooks, whitepapers, tutorials, and other articles, is available on the Web at: www.ibm.com/software/awdtools/caix/library
Related publications
You might want to consult the following publications, which are also referenced throughout this document: v Using the GNU Compiler Collection (GCC), available at http://gcc.gnu.org/onlinedocs/
Technical support
Additional technical support is available from the XL C Support page. This page provides a portal with search capabilities to a large selection of technical support FAQs and other support documents. You can find the XL C Support page on the Web at: www.ibm.com/software/awdtools/caix/support If you cannot find what you need, you can e-mail: [email protected] For the latest information about XL C, visit the product information site at: www.ibm.com/software/awdtools/caix
xiii
xiv
XL C Language Reference
Scope
The scope of an identifier is the largest region of the program text in which the identifier can potentially be used to refer to its object. The meaning of the identifier depends upon the context in which the identifier is used. Scope is the general context used to distinguish the meanings of names.
The scope of an identifier is possibly noncontiguous. One of the ways that breakage occurs is when the same name is reused to declare a different entity, thereby creating a contained declarative region (inner) and a containing declarative region (outer). Thus, point of declaration is a factor affecting scope. Exploiting the possibility of a noncontiguous scope is the basis for the technique called information hiding. The concept of scope that exists in C was expanded and refined in C++. The following table shows the kinds of scopes and the minor differences in terminology.
Table 4. Differences in terminology between C and C++ C block function Function prototype file C++ local function Function prototype global namespace namespace class
In all declarations, the identifier is in scope before the initializer. The following example demonstrates this:
int x; void f() { int x = x; }
The x declared in function f() has local scope, not global scope.
Block scope
A name has local scope or block scope if it is declared in a block. A name with local scope can be used in that block and in blocks enclosed within that block, but the name must be declared before it is used. When the block is exited, the names declared in the block are no longer available. Parameter names for a function have the scope of the outermost block of that function. Also, if the function is declared and not defined, these parameter names have function prototype scope. When one block is nested inside another, the variables from the outer block are usually visible in the nested block. However, if the declaration of a variable in a nested block has the same name as a variable that is declared in an enclosing block, the declaration in the nested block hides the variable that was declared in the enclosing block. The original declaration is restored when program control returns to the outer block. This is called block visibility. Name resolution in a local scope begins in the immediate scope in which the name is used and continues outward with each enclosing scope. The order in which scopes are searched during name resolution causes the phenomenon of information hiding. A declaration in an enclosing scope is hidden by a declaration of the same identifier in a nested scope.
XL C Language Reference
Function scope
The only type of identifier with function scope is a label name. A label is implicitly declared by its appearance in the program text and is visible throughout the function that declares it. A label can be used in a goto statement before the actual label is seen. Related information v Labeled statements on page 131
File scope
A name has file scope if the identifiers declaration appears outside of any block. A name with file scope and internal linkage is visible from the point where it is declared to the end of the translation unit. Related information v Internal linkage on page 5
Examples of scope in C
The following example declares the variable x on line 1, which is different from the x it declares on line 2. The declared variable on line 2 has function prototype scope and is visible only up to the closing parenthesis of the prototype declaration. The variable x declared on line 1 resumes visibility after the end of the prototype declaration.
1 2 3 4 5 6 7 int x = 4; /* variable x defined with file scope */ long myfunc(int x, long y); /* variable x has function */ /* prototype scope */ int main(void) { /* . . . */ }
The following program illustrates blocks, nesting, and scope. The example shows two kinds of scope: file and block. The main function prints the values 1, 2, 3, 0, 3, 2, 1 on separate lines. Each instance of i represents a different variable.
#include <stdio.h> int i = 1; int main(int argc, char * argv[]) { printf("%d\n", i); { int i = 2, j = 3; printf("%d\n%d\n", i, j); { int i = 0; } printf("%d\n", i); } printf("%d\n", i); return 0; }
/* i is redefined in a nested block */ /* previous definitions of i are hidden */ printf("%d\n%d\n", i, j); /* Prints 0, 3 */ /* Prints 2 */
/* Prints 1 */
Namespaces of identifiers
Namespaces are the various syntactic contexts within which an identifier can be used. Within the same context and the same scope, an identifier must uniquely identify an entity. The compiler sets up namespaces to distinguish among identifiers referring to different kinds of entities. Identical identifiers in different namespaces do not interfere with each other, even if they are in the same scope. The same identifier can declare different objects as long as each identifier is unique within its namespace. The syntactic context of an identifier within a program lets the compiler resolve its namespace without ambiguity. Within each of the following four namespaces, the identifiers must be unique. v Tags of these types must be unique within a single scope: Enumerations Structures and unions v Members of structures, unions, and classes must be unique within a single structure, union, or class type. v Statement labels have function scope and must be unique within a function. v All other ordinary identifiers must be unique within a single scope: C function names Variable names Names of function parameters Enumeration constants typedef names. You can redefine identifiers in the same namespace but within enclosed program blocks.
XL C Language Reference
Structure tags, structure members, variable names, and statement labels are in four different namespaces. No name conflict occurs among the items named student in the following example:
int get_item() { struct student /* structure tag */ { char name[20]; /* this structure member may not be named student */ int section; int id; } sam; /* this structure variable should not be named student */ goto student; student:; return 0; student fred; } /* null statement label */
The compiler interprets each occurrence of student by its context in the program. For example, when student appears after the keyword struct, it is a structure tag. The name student may not be used for a structure member of struct student. When student appears after the goto statement, the compiler passes control to the null statement label. In other contexts, the identifier student refers to the structure variable.
Program linkage
Linkage determines whether identifiers that have identical names refer to the same object, function, or other entity, even if those identifiers appear in different translation units. The linkage of an identifier depends on how it was declared. There are three types of linkages: v Internal linkage : identifiers can only be seen within a translation unit. v External linkage : identifiers can be seen (and referred to) in other translation units. v No linkage: identifiers can only be seen in the scope in which they are defined. Linkage does not affect scoping, and normal name lookup considerations apply. Related information v The static storage class specifier on page 36 v The extern storage class specifier on page 37 v Function storage class specifiers on page 156 v Type qualifiers on page 56
Internal linkage
The following kinds of identifiers have internal linkage: v Objects, references, or functions explicitly declared static v Objects or references declared in global scope with the specifier const and neither explicitly declared extern, nor previously declared to have external linkage v Data members of an anonymous union A function declared inside a block will usually have external linkage. An object declared inside a block will usually have external linkage if it is specified extern. If
Chapter 1. Scope and linkage
a variable that has static storage is defined outside a function, the variable has internal linkage and is available from the point where it is defined to the end of the current translation unit. If the declaration of an identifier has the keyword extern and if a previous declaration of the identifier is visible at namespace or global scope, the identifier has the same linkage as the first declaration.
External linkage
In global scope, identifiers for the following kinds of entities declared without the static storage class specifier have external linkage: v An object v A function If an identifier is declared with the extern keyword and if a previous declaration of an object or function with the same identifier is visible, the identifier has the same linkage as the first declaration. For example, a variable or function that is first declared with the keyword static and later declared with the keyword extern has internal linkage. However, a variable or function that has no linkage and was later declared with a linkage specifier will have the linkage that was expressly specified.
No linkage
The following kinds of identifiers have no linkage: v Names that have neither external or internal linkage v Names declared in local scopes (with exceptions like certain entities declared with the extern keyword) v Identifiers that do not represent an object or a function, including labels, enumerators, typedef names that refer to entities with no linkage, type names, function parameters, and template names You cannot use a name with no linkage to declare an entity with linkage. For example, you cannot use the name of a class or enumeration or a typedef name referring to an entity with no linkage to declare an entity with linkage. The following example demonstrates this:
int main() { struct A { }; // extern A a1; typedef A myA; // extern myA a2; }
The compiler will not allow the declaration of a1 with external linkage. Class A has no linkage. The compiler will not allow the declaration of a2 with external linkage. The typedef name myA has no linkage because A has no linkage.
XL C Language Reference
Tokens
Source code is treated during preprocessing and compilation as a sequence of tokens. A token is the smallest independent unit of meaning in a program, as defined by the compiler. There are four different types of tokens: v Keywords v Identifiers v Literals v Punctuators and operators Adjacent identifiers, keywords, and literals must be separated with white space. Other tokens should be separated by white space to make the source code more readable. White space includes blanks, horizontal and vertical tabs, new lines, form feeds, and comments.
Keywords
Keywords are identifiers reserved by the language for special use. Although you can use them for preprocessor macro names, it is considered poor programming style. Only the exact spelling of keywords is reserved. For example, auto is reserved but AUTO is not.
Table 5. C keywords auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while
Notes: 1. The keyword _Imaginary is reserved for future extension of complex number functionality. For current complex number functionality, use _Complex; see Complex literals on page 16 for details. 2. The keyword inline is only recognized under compilation with c99 or -qlanglvl=stdc99 or -qlanglvl=extc99 options (or equivalent pragmas) or with the option -qkeyword=inline. Note that the latter option is enabled by default for the xlc invocation command in the configuration file that is shipped with the compiler. 3. The keyword restrict is only recognized under compilation with c99 or with the -qlanglvl=stdc99 or -qlanglvl=extc99 options (or equivalent pragmas) or the-qkeyword=restrict option.
Notes: 1. The __inline__ keyword uses the GNU C semantics for inline functions. For details, see Linkage of inline functions on page 157. 2. These keywords are recognized only in a vector declaration context, when VMX support is enabled. Related information v -qlanglvl and -qkeyword in the XL C Compiler Reference v Appendix B, Vector data types and literals, on page 197 End of IBM extension
Identifiers
Identifiers provide names for the following language elements: v Functions v Objects v Labels v Function parameters
XL C Language Reference
v v v v
Macros and macro parameters Type definitions Enumerated types and enumerators Structure and union names
An identifier consists of an arbitrary number of letters, digits, or the underscore character in the form:
letter _
letter digit _
Characters in identifiers
The first character in an identifier must be a letter or the _ (underscore) character; however, beginning identifiers with an underscore is considered poor programming style. The compiler distinguishes between uppercase and lowercase letters in identifiers. For example, PROFIT and profit represent different identifiers. If you specify a lowercase a as part of an identifier name, you cannot substitute an uppercase A in its place; you must use the lowercase letter. The universal character names for letters and digits outside of the basic source character set are allowed at the C99 language level, under compilation with the c99 invocation command, the -qlanglvl=extc99 or -qlanglvl=stdc99 options or related pragmas, or the-qlanglvl=ucs option. The dollar sign can appear in identifier names when compiled using the -qdollar compiler option or at one of the extended language levels that encompasses this option.
IBM
Reserved identifiers
Identifiers with two initial underscores or an initial underscore followed by an uppercase letter are reserved globally for use by the compiler. Identifiers that begin with a single underscore are reserved as identifiers with file scope in both the ordinary and tag namespaces. Although the names of system calls and library functions are not reserved words if you do not include the appropriate headers, avoid using them as identifiers. Duplication of a predefined name can lead to confusion for the maintainers of your code and can cause errors at link time or run time. If you include a library in a program, be aware of the function names in that library to avoid name duplications. You should always include the appropriate headers when using standard library functions.
Chapter 2. Lexical elements
where function-name is the name of the lexically-enclosing function. For debugging purposes, you can explicitly use the __func__ identifier to return the name of the function in which it appears. For example:
#include <stdio.h> void myfunc(void) { printf("%s\n",__func__); printf("size of __func__ = %d\n", sizeof(__func__)); } int main() { myfunc(); }
When the assert macro is used inside a function definition, the macro adds the name of the enclosing function on the standard error stream. Related information v Function declarations and definitions on page 153
Assembly labels
IBM extension The compiler binds each non-static external variable and function name in the source code to a name that it generates in the object file and any assembly code that is emitted. For compatibility with GCC, the compiler implements an extension to standard C that allows you to specify the name to be used in the object file and assembly code, by applying an assembly label to the declaration of a global variable or function prototype. You can also define names that do not start with an underscore even on systems where an underscore is normally prepended to the name of a function or variable. Assembly label syntax
declarator asm __asm__ __asm ( string_literal ) initializer
The string_literal is a valid assembly name that is to be bound to the given object or function. For a label applied to a function declaration, the name must specify an existing function that is defined in any compilation unit; if no definition is available, a link-time error will occur. For a label applied to a variable declaration, no other definition is required.
10
XL C Language Reference
The following are restrictions on the use of assembly labels: v Assembly labels cannot be specified on local or static variables. v The same assembly label name cannot be applied to multiple identifiers in the same compilation unit. v The assembly label name cannot be the same as any other global identifier name in the same compilation unit, unless the label name and identifier name are used for the same variable or function declaration. v The assembly label cannot be specified on typedef declarations. v An assembly label cannot be the same as a name specified on a different variable or function by a previous #pragma map directive. Similarly, the map name specified by a #pragma map directive cannot be the same as a name specified by a previous assembly label on a different variable or function. v You cannot apply an assembly label to an identifier that has been mapped to a different name by a #pragma map directive on a previous declaration of that variable or function. Similarly, you cannot specify a #pragma map directive on an identifier that has previously been remapped by an assembly label. v If you apply different labels to multiple declarations of the same variable or function, the first specification is honored, and all subsequent assembly labels are ignored with a warning. Related information v #pragma map in the XL C Compiler Reference v The alias function attribute on page 163 v Global variables in specified registers (C only) on page 38 v Inline assembly statements on page 149 v -qreserved_reg in the XL C Compiler Reference End of IBM extension
Literals
The term literal constant, or literal, refers to a value that occurs in a program and cannot be changed. The C language uses the term constant in place of the noun literal. The adjective literal adds to the concept of a constant the notion that we can speak of it only in terms of its value. A literal constant is nonaddressable, which means that its value is stored somewhere in memory, but we have no means of accessing that address. Every literal has a value and a data type. The value of any literal does not change while the program runs and must be in the range of representable values for its type. The following are the available types of literals: v Integer literals v Boolean literals v Floating-point literals
IBM v Vector literals v Character literals
11
v String literals
Integer literals
Integer literals are numbers that do not have a decimal point or an exponential part. They can be represented as: v Decimal integer literals v Hexadecimal integer literals v Octal integer literals An integer literal may have a prefix that specifies its base, or a suffix that specifies its type. Integer literal syntax
decimal_constant octal_constant hexadecimal_constant
l L ll LL u U
u U
l L ll LL
The data type of an integer literal is determined by its form, value, and suffix. The following table lists the integer literals and shows the possible data types. The smallest data type that can represent the constant value is used to store the constant.
Integer literal unsuffixed decimal unsuffixed octal or hexadecimal decimal, octal, or hexadecimal suffixed by u or U decimal suffixed by l or L octal or hexadecimal suffixed by l or L decimal, octal, or hexadecimal suffixed by both u or U, and l or L decimal suffixed by ll or LL Possible data types int, long int, long long int1 int, unsigned int, long int, unsigned long int, long long int1, unsigned long long int1 unsigned int, unsigned long int, unsigned long long int1 long int, long long int1 long int, unsigned long int, long long int1, unsigned long long int1 unsigned long int, unsigned long long int1 long long int
octal or hexadecimal suffixed by ll or long long int, unsigned long long int LL decimal, octal, or hexadecimal suffixed by both u or U, and ll or LL Notes: 1. Requires compilation with c99 or with -qlanglvl=stdc99 or -qlanglvl=extc99 or the equivalent pragmas. unsigned long long int
Related information
12
XL C Language Reference
v Integral types on page 39 v Integral conversions on page 89 v -qlanglvl in the XL C Compiler Reference Decimal integer literals: A decimal integer literal contains any of the digits 0 through 9. The first digit cannot be 0. Integer literals beginning with the digit 0 are interpreted as an octal integer literal rather than as a decimal integer literal. Decimal integer literal syntax
digit_1_to_9
digit_0_to_9
A plus (+) or minus (-) symbol can precede a decimal integer literal. The operator is treated as a unary operator rather than as part of the literal. The following are examples of decimal literals:
485976 -433132211 +20 5
Hexadecimal integer literals: A hexadecimal integer literal begins with the 0 digit followed by either an x or X, followed by any combination of the digits 0 through 9 and the letters a through f or A through F. The letters A (or a) through F (or f) represent the values 10 through 15, respectively. Hexadecimal integer literal syntax
0x 0X
digit_0_to_f digit_0_to_F
Octal integer literals: An octal integer literal begins with the digit 0 and contains any of the digits 0 through 7. Octal integer literal syntax
digit_0_to_7
13
Boolean literals
At the C99 level, C defines true and false as macros in the header file stdbool.h. Related information v Boolean types on page 40 v Boolean conversions on page 90
Floating-point literals
Floating-point literals are numbers that have a decimal point or an exponential part. They can be represented as: v Real literals Decimal floating-point literals Hexadecimal floating-point literals v Complex literals Decimal floating-point literals: A real decimal floating-point constant consists of the following: v An integral part v A decimal point v A fractional part v An exponent part v An optional suffix Both the integral and fractional parts are made up of decimal digits. You can omit either the integral part or the fractional part, but not both. You can omit either the decimal point or the exponent part, but not both. Decimal floating-point literal syntax
. digit
digit exponent f F l L
digit
. exponent
digit
exponent
Exponent:
e E
digit + -
The suffix f or F indicates a type of float, and the suffix l or L indicates a type of
14
XL C Language Reference
long double. If a suffix is not specified, the floating-point constant has a type double. A plus (+) or minus (-) symbol can precede a floating-point literal. However, it is not part of the literal; it is interpreted as a unary operator. The following are examples of decimal floating-point literals:
Floating-point constant 5.3876e4 4e-11 1e+5 7.321E-3 3.2E+4 0.5e-6 0.45 6.e10 Value 53,876 0.00000000004 100000 0.007321 32000 0.0000005 0.45 60000000000
Related information v Floating-point types on page 41 v Floating-point conversions on page 90 v Unary expressions on page 102 Hexadecimal floating-point literals: Real hexadecimal floating constants, which are a C99 feature, consist of the following: v a hexadecimal prefix v a significant part v a binary exponent part v an optional suffix The significant part represents a rational number and is composed of the following: v a sequence of hexadecimal digits (whole-number part) v an optional fraction part The optional fraction part is a period followed by a sequence of hexadecimal digits. The exponent part indicates the power of 2 to which the significant part is raised, and is an optionally signed decimal integer. The type suffix is optional. The full syntax is as follows: Hexadecimal floating-point literal syntax
15
0x 0X
. digit_0_to_f digit_0_to_F
digit_0_to_f digit_0_to_F
exponent
digit_0_to_f digit_0_to_F
exponent
digit_0_to_f digit_0_to_F
exponent
f F l L
Exponent:
p P
digit_0_to_9 + -
The suffix f or F indicates a type of float, and the suffix l or L indicates a type of long double. If a suffix is not specified, the floating-point constant has a type double. You can omit either the whole-number part or the fraction part, but not both. The binary exponent part is required to avoid the ambiguity of the type suffix F being mistaken for a hexadecimal digit. Complex literals: Complex literals, which are a C99 feature, are constructed in two parts: the real part, and the imaginary part. Complex literal syntax
real part + Imaginary part: floating-point constant * _Complex_I imaginary part
Real part:
floating-point constant
The floating-point constant can be specified as a decimal or hexadecimal floating-point constant (including optional suffixes), in any of the formats described in the previous sections. _Complex_I is a macro defined in the complex.h header file, representing the imaginary unit i, the square root of -1.
16
XL C Language Reference
initializes the complex variable varComplex to a value of 2.0 + 2.0i. IBM extension For ease of porting applications developed with GNU C, XL C also allows you to indicate the imaginary part of a complex literal with a suffix, in addition to the standard suffixes that indicate the type of the complex number (float, double, or long double). The simplified syntax for a complex literal using the GNU suffixes is as follows:
real part + imaginary part
real part:
floating-point constant
imaginary part:
floating-point constant imaginary-suffix
floating-point constant can be specified as a decimal or hexadecimal floating-point constant (including optional suffixes), in any of the formats described in the previous sections. imaginary-suffix is one of the suffixes i, I, j, or J, representing the imaginary unit. For example, the declaration
varComplex = 3.0f + 4.0fi;
initializes the complex variable varComplex to a value of 3.0 + 4.0i. End of IBM extension Related information v Complex floating-point types on page 41
Vector literals
IBM extension A vector literal is a constant expression for which the value is interpreted as a vector type. The data type of a vector literal is represented by a parenthesized vector type, and its value is represented by a parenthesized set of constant expressions that represent the vector elements. When all vector elements have the same value, the value of the literal can be represented by a single parenthesized constant expression. Vector literals allow the initialization of vector types.
17
The vector_type is a supported vector type. The constant_expression can be either of the following: v A single expression, which will initialize all elements of the vector to the same value v A comma-separated list of expressions, the number of which is determined by the type of the vector. The number of constant expressions must be exactly: 4 8 16 For vector int, vector long, and vector float types. For vector short and vector pixel types. For vector char types.
For example, for an unsigned integer vector type, the literal could be either of the following:
(vector unsigned int)(10) /* initializes all four elements to a value of 10 (vector unsigned int)(14, 82, 73, 700) /* initializes the first element to 14, the second element to 82, the third element to 73, and the fourth element to 700 */ */
A vector literal can be cast to another vector type. A vector literal cast does not change the bit pattern of the operand: the 128 bits representing the value remains the same before and after the cast. A full list of vector literals is provided in Appendix B, Vector data types and literals, on page 197. Related information v Vector types on page 43 v Initialization of vectors on page 77 End of IBM extension
Character literals
A character literal contains a sequence of characters or escape sequences enclosed in single quotation mark symbols, for example c. A character literal may be prefixed with the letter L, for example Lc. A character literal without the L prefix is an ordinary character literal or a narrow character literal. A character literal with the L prefix is a wide character literal. An ordinary character literal that contains more than one character or escape sequence (excluding single quotes (), backslashes (\) or new-line characters) is a multicharacter literal. The type of a narrow character literal is int. The type of a wide character literal is wchar_t. The type of a multicharacter literal is int. Character literal syntax
18
XL C Language Reference
' L
character escape_sequence
'
At least one character or escape sequence must appear in the character literal, and the character literal must appear on a single logical source line. The characters can be from the source program character set. You can represent the double quotation mark symbol by itself, but to represent the single quotation mark symbol, you must use the backslash symbol followed by a single quotation mark symbol ( \ escape sequence). (See Escape sequences on page 23 for a list of other characters that are represented by escape characters.) Outside of the basic source character set, the universal character names for letters and digits are allowed at the C99 language level. To enable universal character names, you must compile with the c99 invocation command, the -qlanglvl=extc99 or -qlanglvl=stdc99 options or related pragmas , or the -qlanglvl=ucs option. The following are examples of character literals:
a \ L0 (
Related information v Source program character set on page 22 v The Unicode standard on page 24 v Character types on page 41
String literals
A string literal contains a sequence of characters or escape sequences enclosed in double quotation mark symbols. A string literal with the prefix L is a wide string literal. A string literal without the prefix L is an ordinary or narrow string literal. The type of a narrow string literal is array of char. The type of a wide string literal is array of wchar_t. A null ('\0') character is appended to each string. For a wide string literal, the value '\0' of type wchar_t is appended. By convention, programs recognize the end of a string by finding the null character. String literal syntax
" L
character escape_sequence
"
Multiple spaces contained within a string literal are retained. Use the escape sequence \n to represent a new-line character as part of the string. Use the escape sequence \\ to represent a backslash character as part of the string.
19
You can represent a single quotation mark symbol either by itself or with the escape sequence \. You must use the escape sequence \" to represent a double quotation mark. Outside of the basic source character set, the universal character names for letters and digits are allowed at the C99 language level. To enable universal character names, you must compile with the c99 invocation command, the -qlanglvl=extc99 or -qlanglvl=stdc99 options or related pragmas, or the -qlanglvl=ucs option.
IBM The Pascal string form of a string literal is also accepted, provided that you compile with the -qmacpstr option.
To continue a string on the next line, use the line continuation character (\ symbol) followed by optional whitespace and a new-line character (required). For example:
char *mail_addr = "Last Name First Name MI 893 City Province Postal code "; Street Address \
In the following example, the string literal second causes a compile-time error.
char *first = "This string continues onto the next\ line, where it ends."; /* compiles successfully. char *second = "The comment makes the \ */ invisible to the compiler."; /* continuation symbol /* compilation error. */ */
Note: When a string literal appears more than once in the program source, how that string is stored depends on whether strings are read-only or writeable. By default, the compiler considers strings to be read-only. XL C may allocate only one location for a read-only string; all occurrences will refer to that one location. However, that area of storage is potentially write-protected. If strings are writeable, then each occurrence of the string will have a separate, distinct storage location that is always modifiable. You can use the #pragma strings directive or the -qro compiler option to change the default storage for string literals. Related information v Character types on page 41 v Source program character set on page 22 v The Unicode standard on page 24 v -qro in the XL C Compiler Reference v #pragma strings in the XL C Compiler Reference v -qsourcetype in the XL C Compiler Reference v -qmacpstr in the XL C Compiler Reference String concatenation: Another way to continue a string is to have two or more consecutive strings. Adjacent string literals will be concatenated to produce a single string. For example:
"hello " "there" "hello" "there" /* is equivalent to "hello there" /* is equivalent to "hellothere" */ */
20
XL C Language Reference
Characters in concatenated strings remain distinct. For example, the strings "\xab" and "3" are concatenated to form "\xab3 ". However, the characters \xab and 3 remain distinct and are not merged to form the hexadecimal character \xab3 . If a wide string literal and a narrow string literal are adjacent, as in the following:
"hello " L"there"
the result is a wide string literal. Following any concatenation, '\0' of type char is appended at the end of each string. For a wide string literal, '\0' of type wchar_t is appended. For example:
char *first = "Hello "; char *second = "there"; char *third = "Hello " "there"; /* stored as "Hello \0" */ /* stored as "there\0" */ /* stored as "Hello there\0" */
Alternative tokens
The following table lists alternative representations for some operators and punctuators:
Operator or punctuator { } [ ] # ## Alternative representation <% %> <: :> %: %:%:
21
In addition to the operators and punctuators listed above, the C99 language level provides the following alternative representations, defined as macros in the header file iso646.h.
Operator or punctuator && | || ^ ~ & &= |= ^= ! != Alternative representation and bitor or xor compl bitand and_eq or_eq xor_eq not not_eq
v v
v v
IBM Depending on the compiler option, other specialized identifiers, such as the dollar sign ($) or characters in national character sets, may be allowed to appear in an identifier.
Multibyte characters
The compiler recognizes and supports the additional characters (the extended character set) which you can meaningfully use in string literals and character constants. The support for extended characters includes the multibyte character sets.
22
XL C Language Reference
A multibyte character is a character whose bit representation fits into one or more bytes. To instruct the compiler to recognize multibyte character sets as source input, be sure to compile with the -qmbcs option. Related information v Character literals on page 18 v The Unicode standard on page 24 v Character types on page 41 v -qmbcs in the XL C Compiler Reference v Multibyte character support in the XL C Compiler Reference
Escape sequences
You can represent any member of the execution character set by an escape sequence. They are primarily used to put nonprintable characters in character and string literals. For example, you can use escape sequences to put such characters as tab, carriage return, and backspace into an output stream. Escape character syntax
\ escape_sequence_character x hexadecimal_digits octal_digits
An escape sequence contains a backslash (\) symbol followed by one of the escape sequence characters or an octal or hexadecimal number. A hexadecimal escape sequence contains an x followed by one or more hexadecimal digits (0-9, A-F, a-f). An octal escape sequence uses up to three octal digits (0-7). The value of the hexadecimal or octal number specifies the value of the desired character or wide character. Note: The line continuation sequence (\ followed by a new-line character) is not an escape sequence. It is used in character strings to indicate that the current line of source code continues on the next line. The escape sequences and the characters they represent are:
Escape sequence \a \b \f \n \r \t \v \ \ \? \\ Character represented Alert (bell, alarm) Backspace Form feed (new page) New-line Carriage return Horizontal tab Vertical tab Single quotation mark Double quotation mark Question mark Backslash
The value of an escape sequence represents the member of the character set used at run time. Escape sequences are translated during preprocessing. For example, on
23
a system using the ASCII character codes, the value of the escape sequence \x56 is the letter V. On a system using EBCDIC character codes, the value of the escape sequence \xE5 is the letter V. Use escape sequences only in character constants or in string literals. An error message is issued if an escape sequence is not recognized. In string and character sequences, when you want the backslash to represent itself (rather than the beginning of an escape sequence), you must use a \\ backslash escape sequence. For example:
cout << "The escape sequence \\n." << endl;
24
XL C Language Reference
C99 disallows the hexadecimal values representing characters in the basic character set (base source code set) and the code points reserved by ISO/IEC 10646 for control characters. The following characters are also disallowed: v Any character whose short identifier is less than 00A0. The exceptions are 0024 ($), 0040 (@), or 0060 (`). v Any character whose short identifier is in the code point range D800 through DFFF inclusive.
UTF literals
IBM extension The C Standards Committee has approved the implementation of u-literals and U-literals to support Unicode UTF-16 and UTF-32 character literals, respectively. To enable support for UTF literals in your source code, you must compile with the option -qutf enabled. The following table shows the syntax for UTF literals.
Table 9. UTF literals Syntax ucharacter ucharacter-sequence Ucharacter Ucharacter-sequence Explanation Denotes a UTF-16 character. Denotes an array of UTF-16 characters. Denotes a UTF-32 character. Denotes an array of UTF-32 characters.
XL C implements the macros uint_least16_t and uint_least32_t, which are defined in the header file stdint.h, as data types for UTF-16 and UTF-32 characters. The following example defines an array of uint_least16_t, including the characters represented by code points 1234 and 8180:
#include <stdint.h> uint_least16_t msg[] = u"ucs characters \u1234 and \u8180 ";
Related information v -qutf in the XL C Compiler Reference String concatenation of u-literals: The u-literals and U-literals follow the same concatenation rule as wide character literals: the normal character string is widened if they are present. The following shows the allowed combinations. All other combinations are invalid.
Combination ua ub ua b a ub Ua Ub Ua b a Ub Result uab uab uab Uab Uab Uab
Multiple concatentations are allowed, with these rules applied recursively. Related information
Chapter 2. Lexical elements
25
Digraph characters
You can represent unavailable characters in a source program by using a combination of two keystrokes that are called a digraph character. The preprocessor reads digraphs as tokens during the preprocessor phase. The digraph characters are:
%: or %% <: :> <% %> %:%: or %%%% # [ ] { } ## number sign left bracket right bracket left brace right brace preprocessor macro concatenation operator
You can create digraphs by using macro concatenation. XL C does not replace digraphs in string literals or in character literals. For example:
char *s = "<%%>"; // stays "<%%>" switch (c) { case <% : { /* ... */ } // stays <% case %> : { /* ... */ } // stays %> }
Trigraph sequences
Some characters from the C character set are not available in all environments. You can enter these characters into a C source program using a sequence of three characters called a trigraph. The trigraph sequences are:
Trigraph ??= ??( ??) ??< ??> ??/ ?? ??! ??Single character # [ ] { } \ ^ | ~ capription pound sign left bracket right bracket left brace right brace backslash caret vertical bar tilde
The preprocessor replaces trigraph sequences with the corresponding single-character representation. For example,
some_array??(i??) = n;
Represents:
some_array[i] = n;
26
XL C Language Reference
Comments
A comment is text replaced during preprocessing by a single space character; the compiler therefore ignores all comments. There are two kinds of comments: v The /* (slash, asterisk) characters, followed by any sequence of characters (including new lines), followed by the */ characters. This kind of comment is commonly called a C-style comment. v The // (two slashes) characters followed by any sequence of characters. A new line not immediately preceded by a backslash terminates this form of comment. This kind of comment is commonly called a single-line comment or a C++ comment. A C++ comment can span more than one physical source line if it is joined into one logical source line with line-continuation (\) characters. The backslash character can also be represented by a trigraph. C++ comments are enabled in C when you compile with c99, or with the -qlanglvl=stdc99 or -qlanglvl=extc99 options or equivalent pragmas, or -qcpluscmt. Note that the latter option is enabled by default for xlc in the configuration file that is shipped with the compiler. You can put comments anywhere the language allows white space. You cannot nest C-style comments inside other C-style comments. Each comment ends at the first occurrence of */. You can also include multibyte characters; to instruct the compiler to recognize multibyte characters in the source code, compile with the -qmbcs option. Note: The /* or */ characters found in a character constant or string literal do not start or end comments. In the following program, the second printf() is a comment:
#include <stdio.h> int main(void) { printf("This program has a comment.\n"); /* printf("This is a comment line and will not print.\n"); */ return 0; }
Because the second printf() is equivalent to a space, the output of this program is:
This program has a comment.
Because the comment delimiters are inside a string literal, printf() in the following program is not a comment.
#include <stdio.h> int main(void) { printf("This program does not have \ /* NOT A COMMENT */ a comment.\n"); return 0; }
27
In test_function, the compiler reads the first /* through to the first */. The second */ causes an error. To avoid commenting over comments already in the source code, you should use conditional compilation preprocessor directives to cause the compiler to bypass sections of a program. For example, instead of commenting out the above statements, change the source code in the following way:
/* A program with conditional compilation to avoid nested comments. */ #define TEST_FUNCTION 0 #include <stdio.h> int main(void) { test_function(); return 0; } int test_function(void) { int number; char letter; #if TEST_FUNCTION number = 55; letter = A; /*number = 44;*/ #endif /*TEST_FUNCTION */ }
You can nest single line comments within C-style comments. For example, the following program will not output anything:
#include <stdio.h> int main(void) { /* printf("This line will not print.\n"); // This is a single line comment // This is another single line comment
28
XL C Language Reference
Note: You can also use the #pragma comment directive to place comments into an object module. Related information v -qmbcs, -qlanglvl, and -qcpluscmt in the XL C Compiler Reference v Multibyte character support in the XL C Compiler Reference
29
30
XL C Language Reference
31
Table 10. C data types Data object integer types floating-point types1 character types Booleans void type pointers arrays structures unions enumerations + +
2
Basic + +
Compound Built-in + + + + + + + + + + + +
Userdefined
Scalar + + + + + +
Aggregate
+ + + + see note3 +
Notes: 1. Although complex floating-point types are represented internally as an array of two elements, they behave in the same way as real floating-pointing types in terms of alignment and arithmetic operations, and can therefore be considered scalar types. 2. The void type is really an incomplete type, as discussed in Incomplete types. 3. The C standard does not classify enumerations as either scalar or aggregate.
Incomplete types
The following are incomplete types: v The void type v Arrays of unknown size v Arrays of elements that are of incomplete type v Structure, union, or enumerations that have no definition However, if an array size is specified by [*], indicating a variable length array, the size is considered as having been specified, and the array type is then considered a complete type. For more information, see Variable length arrays on page 72. The following examples illustrate incomplete types:
void *incomplete_ptr; struct dimension linear; /* no previous definition of dimension */
Compatible types
In C, compatible types are defined as: v two types that can be used together without modification (as in an assignment expression) v two types that can be substituted one for the other without modification
32
XL C Language Reference
When two compatible types are combined, the result is a composite type. Determining the resultant composite type for two compatible types is similar to following the usual binary conversions of integral types when they are combined with some arithmetic operators. Obviously, two types that are identical are compatible; their composite type is the same type. Less obvious are the rules governing type compatibility of non-identical types, user-defined types, type-qualified types, and so on. Type specifiers on page 39 discusses compatibility for basic and user-defined types in C. Related information v Compatibility of arrays on page 73 v Compatibility of pointers (C only) on page 70 v Compatible functions on page 156
Note: The C99 standard no longer requires that all declarations appear at the beginning of a function before the first statement. As in C++, you can mix declarations with other statements in your code. Declarations determine the following properties of data objects and their identifiers: v Scope, which describes the region of program text in which an identifier can be used to access its object v Visibility, which describes the region of program text from which legal access can be made to the identifiers object v Duration, which defines the period during which the identifiers have real, physical objects allocated in memory v Linkage, which describes the correct association of an identifier to one particular object v Type, which determines how much memory is allocated to an object and how the bit patterns found in the storage allocation of that object should be interpreted by the program The elements of a declaration for a data object are as follows: v Storage class specifiers, which specify storage duration and linkage
Chapter 3. Data objects and declarations
33
v v v v
Type specifiers, which specify data types Type qualifiers, which specify the mutability of data values Declarators, which introduce and include identifiers Initializers, which initialize storage with initial values IBM extension
In addition, for compatibility with GCC, XL C allows you to use attributes to modify the properties of data objects. Type attributes, which can be used to modify the definition of user-defined types, are described in Type attributes on page 61. Variable attributes, which can be used to modify the declaration of variables, are described in Variable attributes on page 83. End of IBM extension All declarations have the form: Data declaration syntax
Tentative definitions
A tentative definition is any external data declaration that has no storage class specifier and no initializer. A tentative definition becomes a full definition if the end of the translation unit is reached and no definition has appeared with an initializer for the identifier. In this situation, the compiler reserves uninitialized space for the object defined. The following statements show normal definitions and tentative definitions.
int i1 = 10; /* definition, external linkage */ static int i2 = 20; /* definition, internal linkage */ extern int i3 = 30; /* definition, external linkage */ int i4; /* tentative definition, external linkage */ static int i5; /* tentative definition, internal linkage */ int int int int int i1; i2; i3; i4; i5; /* /* /* /* /* valid tentative definition */ not legal, linkage disagreement with previous */ valid tentative definition */ valid tentative definition */ not legal, linkage disagreement with previous */
34
XL C Language Reference
Related information v Function storage class specifiers on page 156 v Initializers on page 73
35
36
XL C Language Reference
of of of of of
1 2 3 4 5
Because x is a static variable, it is not reinitialized to 0 on successive calls to f. Related information v Initialization and storage classes on page 74 v Internal linkage on page 5
37
compiler does not allocate a machine register for a register object, the object is treated as having the storage class specifier auto. An object having the register storage class specifier must be defined within a block or declared as a parameter to a function. The following restrictions apply to the register storage class specifier: v You cannot use pointers to reference objects that have the register storage class specifier. You cannot use the register storage class specifier when declaring objects in global scope. v A register does not have an address. Therefore, you cannot apply the address operator (&) to a register variable. v
The register_specifier is a string representing a hardware register. The register name is CPU-specific. XL C supports the following register names on the PowerPC: v r0 to r31 general purpose registers v f0 to f31 floating point registers v v0 to v31 vector registers The following are the rules of use for register variables: v General purpose registers can only be reserved for variables of integer or pointer type.
38
XL C Language Reference
v Floating point registers can only be reserved for variables of float, double, or 64-bit long double type. v Vector registers can only be reserved for variables of vector type. v Variables of long long type cannot reserve registers. v A global register variable cannot be initialized. v The register dedicated for a global register variable should not be a volatile register, or the value stored into the global variable might not be preserved across a function call. v A global register variable can only reserve a register that is not already reserved by another global register variable. v The same global register variable cannot reserve more than one register. v A register variable should not be used in an OpenMP clause or OpenMP parallel or work-sharing region. v The register specified in the global register declaration is reserved for the declared variable only in the compilation unit in which the register declaration is specified. The register is not reserved in other compilation units unless you place the global register declaration in a common header file, or use the -qreserved_reg compiler option. Related information v Assembly labels on page 10 v Inline assembly statements on page 149 v -qreserved_reg in the XL C Compiler Reference End of IBM extension
Type specifiers
Type specifiers indicate the type of the object being declared. The following are the available kinds of type specifiers: v Fundamental or built-in types: Arithmetic types - Integral types - Boolean types - Floating-point types - Character types The void type v User-defined types. Related information v Function return type specifiers on page 159
Integral types
Integer types fall into the following categories: v Signed integer types: signed char short int int long int
Chapter 3. Data objects and declarations
39
long long int v Unsigned integer types: unsigned char unsigned short int unsigned int unsigned long int unsigned long long int The unsigned prefix indicates that the object is a nonnegative integer. Each unsigned type provides the same size storage as its signed equivalent. For example, int reserves the same storage as unsigned int. Because a signed type reserves a sign bit, an unsigned type can hold a larger positive integer value than the equivalent signed type. The declarator for a simple integer definition or declaration is an identifier. You can initialize a simple integer definition with an integer constant or with an expression that evaluates to a value that can be assigned to an integer. Related information v Integer literals on page 12 v Integral conversions on page 89 v Arithmetic conversions and promotions on page 89
Boolean types
A Boolean variable can be used to hold the integer values 0 or 1, or the literals true or false, which are implicitly promoted to the integers 0 and 1 whenever an arithmetic value is necessary. The Boolean type is unsigned and has the lowest ranking in its category of standard unsigned integer types; it may not be further qualified by the specifiers signed, unsigned, short, or long. In simple assignments, if the left operand is a Boolean type, then the right operand must be either an arithmetic type or a pointer. Boolean types are a C99 feature. To declare a Boolean variable, use the _Bool type IBM specifier. The token bool is recognized as a keyword in C only when used in a vector declaration context and VMX support is enabled. You can use Boolean types make Boolean logic tests. A Boolean logic test is used to express the results of a logical operation. For example:
_Bool f(int a, int b) { return a==b; }
If a and b have the same value, f returns true. If not, f returns false. Related information v Boolean literals on page 14 v Boolean conversions on page 90 v Appendix B, Vector data types and literals, on page 197
40
XL C Language Reference
Floating-point types
Floating-point type specifiers fall into the following categories: v Real floating-point types: float double long double v Complex floating-point types The magnitude range of float is approximately 1.2e-38 to 3.4e38. The magnitude range of double or long double is approximately 2.2e-308 to 1.8e308. If a floating-point constant is too large or too small, the result is undefined by the language. The declarator for a simple floating-point declaration is an identifier. Initialize a simple floating-point variable with a float constant or with a variable or expression that evaluates to an integer or floating-point number. Note: If you do not add the f suffix to a floating-point literal, that number will be of type double. If you initialize an object of type float with an object of type double, the compiler will implicitly convert the object of type double to an object of type float. Related information v Floating-point literals on page 14 v Floating-point conversions on page 90 v Arithmetic conversions and promotions on page 89
Related information v Complex literals on page 16 v Arithmetic conversions and promotions on page 89 v The __real__ and __imag__ operators on page 111
Character types
Character types fall into the following categories: v Narrow character types:
Chapter 3. Data objects and declarations
41
char signed char unsigned char v Wide character type wchar_t The char specifier is an integral type. The wchar_t type specifier is an integral type that has enough storage to represent a wide character literal. (A wide character literal is a character literal that is prefixed with the letter L, for example Lx) A char is a distinct type from signed char and unsigned char, and the three types are not compatible. If it does not matter if a char data object is signed or unsigned, you can declare the object as having the data type char. Otherwise, explicitly declare signed char or unsigned char to declare numeric variables that occupy a single byte. When a char (signed or unsigned) is widened to an int, its value is preserved. By default, char behaves like an signed char. To change this default, you can use the -qchars option or the #pragma chars directive. See #pragma chars and -qchars in the XL C Compiler Reference for more information. Related information v Character literals on page 18 v String literals on page 19 v Arithmetic conversions and promotions on page 89
42
XL C Language Reference
The presence of a type qualifier changes the type. That is, const int is not the same type as int, and therefore the two types are not compatible.
Vector types
IBM extension XL C supports Vector Multimedia Extension (VMX) technology through language extensions. XL C implements the AltiVec Programming Interface specification with an extended syntax that allows type qualifiers and storage class specifiers to precede the keyword vector (or its alternate spelling, __vector) in a declaration. The keyword vector is recognized in a declaration context only when used as a type specifier and when VMX support is enabled. The keywords pixel and bool are recognized as valid type specifiers only when preceded by the keyword vector or __vector. To keep your source code maximally portable, avoid using vector, pixel, or bool as keywords or identifiers in your program. Use the underscore versions of the specifiers vector and pixel (__vector and __pixel) in declarations. Most of the legal forms of the syntax are captured in the following diagram. Some variations have been omitted from the diagram for the sake of clarity: type qualifiers such as const and storage class specifiers such as static can appear in any order within the declaration, as long as neither immediately follows the keyword vector (or __vector). Vector declaration syntax
type_qualifier storage_class_specifier vector __vector bool signed unsigned char short int int long int pixel __pixel float
Notes: 1. The long type specifier is deprecated in a vector context. 2. Duplicate type specifiers are ignored in a vector declaration context. In particular, long long is treated as long. 3. A long vector type is compatible with the corresponding int vector type (supported in 32-bit mode only). All vector types are aligned on a 16-byte boundary. An aggregate that contains one or more vector types is aligned on a 16-byte boundary, and padded, if necessary, so that each member of vector type is also 16-byte aligned.
43
The indirection operator * has been extended to handle pointer to vector types. A vector pointer should point to a memory location that has 16-byte alignment. However, the compiler does not enforce this constraint. Dereferencing a vector pointer maintains the vector type and its 16-byte alignment. If a program dereferences a vector pointer that does not contain a 16-byte aligned address, the behavior is undefined. Pointer arithmetic is defined for pointer to vector types. Given:
vector unsigned int *v;
the expression v + 1 represents a pointer to the vector following v. Related information v Vector literals on page 17 v Initialization of vectors on page 77 v Appendix B, Vector data types and literals, on page 197
User-defined types
The following are user-defined types: v Structures and unions v Enumerations v typedef definitions Related information v Type attributes on page 61
44
XL C Language Reference
You can declare a structure or union type separately from the definition of variables of that type, as described in Structure and union type definition and Structure and union variable declarations on page 49; or you can define a structure or union data type and all variables that have that type in one statement, as described in Structure and union type and variable definitions in a single statement on page 50. Structures and unions are subject to alignment considerations. For a complete discussion of alignment, see Aligning data in the XL C Programming Guide.
struct union
{ tag_identifier
member_declaration ;
The tag_identifier gives a name to the type. If you do not provide a tag name, you must put all variable definitions that refer to the type within the declaration of the type, as described in Structure and union type and variable definitions in a single statement on page 50. Similarly, you cannot use a type qualifier with a structure or union definition; type qualifiers placed in front of the struct or union keyword can only apply to variables that are declared within the type definition. Related information v The aligned type attribute on page 62 v The packed type attribute on page 62
Member declarations
The list of members provides a structure or union data type with a description of the values that can be stored in the structure or union. The definition of a member has the form of a standard variable declaration. The names of member variables must be distinct within a single structure or union, but the same member name may be used in another structure or union type that is defined within the same scope, and may even be the same as a variable, function, or type name. A structure or union member may be of any type except: v any variably modified type v any void type v a function v any incomplete type Because incomplete types are not allowed as members, a structure or union type may not contain an instance of itself as a member, but is allowed to contain a pointer to an instance of itself. As a special case, the last element of a structure with more than one member may have an incomplete array type, which is called a flexible array member, as described in Flexible array members on page 46.
45
IBM As an extension to Standard C for compatibility with GNU C, XL C also allows zero-extent arrays as members of structures and unions, as described in Zero-extent array members on page 47.
A member that does not represent a bit field can be qualified with either of the type qualifiers volatile or const. The result is an lvalue. Structure members are assigned to memory addresses in increasing order, with the first component starting at the beginning address of the structure name itself. To allow proper alignment of components, padding bytes may appear between any consecutive members in the structure layout. The storage allocated for a union is the storage required for the largest member of the union (plus any padding that is required so that the union will end at a natural boundary of its member having the most stringent requirements). All of a unions components are effectively overlaid in memory: each member of a union is allocated storage starting at the beginning of the union, and only one member can occupy the storage at a time. For this reason, variably modified types may not be declared as union members. Flexible array members: A flexible array member, which is a C99 feature, can be an element of a structure with more than one named member. A flexible array member can be used to access a variable-length object. The flexible array member must be the last element of such a structure, and it has incomplete type. It is declared with an empty index, as follows: array_identifier[ ]; For example, b is a flexible array member of Foo.
struct Foo{ int a; int b[]; };
Since a flexible array member has incomplete type, you cannot apply the sizeof operator to a flexible array. Any structure containing a flexible array member cannot be a member of another structure or array. IBM extension For compatibility with GNU C, XL C extends Standard C, to ease the restrictions on flexible arrays and allow the following: v Flexible array members can be declared in any part of a structure, not just as the last member. v Structures containing flexible array members can be members of other structures. v Flexible array members can be statically initialized. In the following example:
struct Foo{ int a; int b[]; }; struct foo foo1 = { 55, {6, 8, 10} }; struct foo foo2 = { 55, {15, 6, 14, 90} };
46
XL C Language Reference
foo1 creates an array b of 3 elements, which are initialized to 6, 8, and 10; while foo2 creates an array of 4 elements, which are initialized to 15, 6, 14, and 90. Flexible array members can only be initialized if they are contained in the outermost part of nested structures. Members of inner structures cannot be initialized. End of IBM extension Related information v Variable length arrays on page 72 Zero-extent array members: IBM extension A zero-extent array is an array with no dimensions. Like a flexible array member, a zero-extent array can be used as a kind of template for array members whose size are determined dynamically at run time. Like a flexible array member, a zero-extent member must be the last element of a structure or union with more than one member. It must explicitly declared with zero as its dimension:
array_identifier[0]
Otherwise, it must be initialized as a dyamically-allocated array. Zero-extent array members can only be initialized if they are contained in the outermost part of nested structures. Members of inner structures cannot be initialized. End of IBM extension Bit field members: C allows integer members to be stored into memory spaces smaller than the compiler would ordinarily allow. These space-saving structure members are called bit fields, and their width in bits can be explicitly declared. Bit fields are used in programs that must force a data structure to correspond to a fixed hardware representation and are unlikely to be portable. Bit field member declaration syntax
type_specifier declarator : constant_expression ;
The constant_expression is a constant integer expression that indicates the field width in bits. A bit field declaration may not use either of the type qualifiers const or volatile. In C99, the allowable data types for a bit field include qualified and unqualified _Bool, signed int, and unsigned int. The default integer type for a bit field is unsigned.
Chapter 3. Data objects and declarations
47
The maximum bit-field length is 64 bits. For portability, do not use bit fields greater than 32 bits in size. The following structure has three bit-field members kingdom, phylum, and genus, occupying 12, 6, and 2 bits respectively:
struct taxonomy { int kingdom : 12; int phylum : 6; int genus : 2; };
When you assign a value that is out of range to a bit field, the low-order bit pattern is preserved and the appropriate bits are assigned. The following restrictions apply to bit fields. You cannot: v Define an array of bit fields v Take the address of a bit field v Have a pointer to a bit field v Have a reference to a bit field If a series of bit fields does not add up to the size of an int, padding can take place. The amount of padding is determined by the alignment characteristics of the members of the structure. In some instances, bit fields can cross word boundaries. Bit fields with a length of 0 must be unnamed. Unnamed bit fields cannot be referenced or initialized. The following example demonstrates padding, and is valid for all implementations. Suppose that an int occupies 4 bytes. The example declares the identifier kitchen to be of type struct on_off:
struct on_off { unsigned light : 1; unsigned toaster : 1; int count; /* 4 bytes */ unsigned ac : 4; unsigned : 4; unsigned clock : 1; unsigned : 0; unsigned flag : 1; } kitchen ;
The structure kitchen contains eight members totalling 16 bytes. The following table describes the storage that each member occupies:
Member name light toaster (padding 30 bits) count ac (unnamed field) clock (padding 23 bits) flag Storage occupied 1 bit 1 bit To the next int boundary The size of an int (4 bytes) 4 bits 4 bits 1 bit To the next int boundary (unnamed field) 1 bit
48
XL C Language Reference
storage_class_specifier type_qualifier
struct union
tag_identifier declarator ;
The tag_identifier indicates the previously-defined data type of the structure or union. You can declare structures or unions having any storage class. The storage class specifier and any type qualifiers for the variable must appear at the beginning of the statement. Structures or unions declared with the register storage class specifier are treated as automatic variables. The following example defines structure type address:
struct address { int street_no; char *street_name; char *city; char *prov; char *postal_code; };
Related information v The aligned variable attribute on page 85 v The __align qualifier on page 59 v The packed variable attribute on page 86 v Initialization of structures and unions on page 78 v Compatibility of structures, unions, and enumerations (C only) on page 53 v Dot operator . on page 101 v Arrow operator > on page 101
49
Note that because this example does not name the data type, length is the only variable that can have this data type. Putting an identifier after struct or union lets you declare additional variables of this data type later in the program. To specify a storage class specifier for the variable or variables, you must put the storage class specifier at the beginning of the statement. For example:
static struct { int street_no; char *street_name; char *city; char *prov; char *postal_code; } perm_address, temp_address;
In this case, both perm_address and temp_address are assigned static storage. Type qualifiers can be applied to the variable or variables declared in a type definition. Both of the following examples are valid:
volatile struct class1 { char descript[20]; long code; short complete; } file1, file2; struct class1 { char descript[20]; long code; short complete; } volatile file1, file2;
In both cases, the structures file1 and file2 are qualified as volatile. Related information v Initialization of structures and unions on page 78 v Storage class specifiers on page 35 v Type qualifiers on page 56
assign the string "Ontario" to the pointer prov that is in the structure perm_address.
50
XL C Language Reference
All references to members of structures and unions, including bit fields, must be fully qualified. In the previous example, the fourth field cannot be referenced by prov alone, but only by perm_address.prov. Related information v Dot operator . on page 101 v Arrow operator > on page 101
Anonymous unions
An anonymous union is a union without a name. It cannot be followed by a declarator. An anonymous union is not a type; it defines an unnamed object. The member names of an anonymous union must be distinct from other names within the scope in which the union is declared. You can use member names directly in the union scope without any additional member access syntax. For example, in the following code fragment, you can access the data members i and cptr directly because they are in the scope containing the anonymous union. Because i and cptr are union members and have the same address, you should only use one of them at a time. The assignment to the member cptr will change the value of the member i.
void f() { union { int i; char* cptr ; }; /* . . . */ i = 5; cptr = "string_in_union"; // overrides the value 5 }
Enumerations
An enumeration is a data type consisting of a set of named values that represent integral constants, known as enumeration constants. An enumeration also referred to as an enumerated type because you must list (enumerate) each of the values in creating a name for each of them. In addition to providing a way of defining and grouping sets of integral constants, enumerations are useful for variables that have a small number of possible values. You can declare an enumeration type separately from the definition of variables of that type, as described in Enumeration type definition and Enumeration variable declarations on page 53; or you can define an enumeration data type and all variables that have that type in one statement, as described in Enumeration type and variable definitions in a single statement on page 53. Related information v Arithmetic conversions and promotions on page 89
51
The tag_identifier gives a name to the enumeration type. If you do not provide a tag name, you must put all variable definitions that refer to the enumeration type within the declaration of the type, as described in Enumeration type and variable definitions in a single statement on page 53. Similarly, you cannot use a type qualifier with an enumeration definition; type qualifiers placed in front of the enum keyword can only apply to variables that are declared within the type definition. Enumeration members: The list of enumeration members, or enumerators, provides the data type with a set of values. Enumeration member declaration syntax
identifier = enumeration_constant
In C, an enumeration constant is of type int. If a constant expression is used as an initializer, the value of the expression cannot exceed the range of int (that is, INT_MIN to INT_MAX as defined in the header limits.h). The value of a constant is determined in the following way: 1. An equal sign (=) and a constant expression after the enumeration constant gives an explicit value to the constant. The identifier represents the value of the constant expression. 2. If no explicit value is assigned, the leftmost constant in the list receives the value zero (0). 3. Identifiers with no explicitly assigned values receive the integer value that is one greater than the value represented by the previous identifier. The following data type declarations list oats, wheat, barley, corn, and rice as enumeration constants. The number under each constant shows the integer value.
enum grain { oats, wheat, barley, corn, rice }; /* 0 1 2 3 4 */
enum grain { oats=1, wheat, barley, corn, rice }; /* 1 2 3 4 5 */ enum grain { oats, wheat=10, barley, corn=20, rice }; /* 0 10 11 20 21 */
It is possible to associate the same integer with two different enumeration constants. For example, the following definition is valid. The identifiers suspend and hold have the same integer value.
enum status { run, clear=5, suspend, resume, hold=6 }; /* 0 5 6 7 6 */
Each enumeration constant must be unique within the scope in which the enumeration is defined. In the following example, the second declarations of average and poor cause compiler errors:
52
XL C Language Reference
func() { enum score { poor, average, good }; enum rating { below, average, above }; int poor; }
The tag_identifier indicates the previously-defined data type of the enumeration. Related information v Initialization of enumerations on page 80 v Compatibility of structures, unions, and enumerations (C only)
Both examples define the enumeration data type score and the variable rating. rating has the storage class specifier register, the data type enum score, and the initial value good. Combining a data type definition with the definitions of all variables having that data type lets you leave the data type unnamed. For example:
enum { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday } weekday;
defines the variable weekday, which can be assigned any of the specified enumeration constants. However, you can not declare any additional enumeration variables using this set of enumeration constants.
53
union type is the same type. The tag associates the reference with the definition, and effectively acts as the type name. To illustrate this, only the types of structures j and k are compatible in this example:
struct { int a; int b; } h; struct { int a; int b; } i; struct S { int a; int b; } j; struct S k;
Compatible structures may be assigned to each other. Structures or unions with identical members but different tags are not compatible and cannot be assigned to each other. Structures and unions with identical members but using different alignments are not also compatible and cannot be assigned to each other. Since the compiler treats enumeration variables and constants as integer types, you can freely mix the values of different enumerated types, regardless of type compatibility. Compatibility between an enumerated type and the integer type that represents it is controlled by compiler options and related pragmas. For a full discussion of the -qenum compiler option and related pragmas, see -qenum and #pragma enum in the XL C Compiler Reference. Related information v Arithmetic conversions and promotions on page 89 v Structure and union type definition on page 45 v Incomplete types on page 32
typedef definitions
A typedef declaration lets you define your own identifiers that can be used in place of type specifiers such as int, float, and double. A typedef declaration does
54
XL C Language Reference
not reserve storage. The names you define using typedef are not new data types, but synonyms for the data types or combinations of data types they represent. The namespace for a typedef name is the same as other identifiers. The exception to this rule is if the typedef name specifies a variably modified type. In this case, it has block scope. When an object is defined using a typedef identifier, the properties of the defined object are exactly the same as if the object were defined by explicitly listing the data type associated with the identifier. IBM extension typedef definitions are extended to handle vector types, provided that the VMX support is enabled. A vector type can be used in a typedef definition, and the new type name can be used in the usual ways, except for declaring other vectors. In a vector declaration context, a typedef name is disallowed as a type specifier. The following example illustrates a typical usage of typedef with vector types:
typedef vector unsigned short vint16; vint16 v1;
End of IBM extension Related information v Type names on page 66 v Type specifiers on page 39 v Structures and unions on page 44
In the following example, the type of yds is pointer to function with no parameter specified, returning int.
typedef int SCROLL(); extern SCROLL *yds;
In the following typedefs, the token struct is part of the type name: the type of ex1 is struct a; the type of ex2 is struct b.
Chapter 3. Data objects and declarations
55
typedef struct a { char x; } ex1, *ptr1; typedef struct b { char x; } ex2, *ptr2;
Type ex1 is compatible with the type struct a and the type of the object pointed to by ptr1. Type ex1 is not compatible with char, ex2, or struct b.
Type qualifiers
A type qualifier is used to refine the declaration of a variable, a function, and parameters, by specifying whether: v The value of an object can be changed v The value of an object must always be read from memory rather than from a register v More than one pointer can access a modifiable memory address XL C recognizes the following type qualifiers: v const v volatile v restrict v
IBM
__align
When the const and volatile keywords are used with pointers, the placement of the qualifier is critical in determining whether it is the pointer itself that is to be qualified, or the object to which the pointer points. For a pointer that you want to qualify as volatile or const, you must put the keyword between the * and the identifier. For example:
int * volatile x; int * const y = &z; /* x is a volatile pointer to an int */ /* y is a const pointer to the int variable z */
For a pointer to a volatile or const data object, the type specifier and qualifier can be in any order, provided that the qualifier does not follow the * operator. For example:
volatile int *x; or int volatile *x; const int *y; or int const *y; /* x is a pointer to a volatile int /* x is a pointer to a volatile int /* y is a pointer to a const int /* y is a pointer to a const int */ */ */ */
You can put more than one qualifier on a declaration: the compiler ignores duplicate type qualifiers.
56
XL C Language Reference
A type qualifier cannot apply to user-defined types, but only to objects created from a user-defined type. Therefore, the following declaration is illegal:
volatile struct omega { int limit; char code; }
However, if a variable or variables are declared within the same definition of the type, a type qualifier can be applied to the variable or variables by placing at the beginning of the statement or before the variable declarator or declarators. Therefore:
volatile struct omega { int limit; char code; } group;
In both examples, the volatile qualifier only applies to the structure variable group. When type qualifiers are applied to a structure or union, or class variable, they also apply to the members of the structure or union. Related information v Pointers on page 68
57
Accessing any lvalue expression that is volatile-qualified produces a side effect. A side effect means that the state of the execution environment changes. References to an object of type pointer to volatile may be optimized, but no optimization can occur to references to the object to which it points. An explicit cast must be used to assign a value of type pointer to volatile T to an object of type pointer to T. The following shows valid uses of volatile objects.
volatile int * pvol; int *ptr; pvol = ptr; ptr = (int *)pvol; /* Legal */ /* Explicit cast required */
A signal-handling function may store a value in a variable of type sig_atomic_t, provided that the variable is declared volatile. This is an exception to the rule that a signal-handling function may not access variables with static storage duration. An item can be both const and volatile. In this case the item cannot be legitimately modified by its own program but can be modified by some asynchronous process.
Assignments between restricted pointers are limited, and no distinction is made between a function call and an equivalent nested block.
{ int * restrict x; int * restrict y; x = y; // undefined { int * restrict x1 = x; // okay int * restrict y1 = y; // okay x = y1; // undefined } }
In nested blocks containing restricted pointers, only assignments of restricted pointers from outer to inner blocks are allowed. The exception is when the block in
58
XL C Language Reference
which the restricted pointer is declared finishes execution. At that point in the program, the value of the restricted pointer can be carried out of the block in which it was declared. Notes: 1. The restrict qualifier is represented by the following keywords (all have the same semantics): v The restrict keyword is only recognized under compilation with c99 or with the -qlanglvl=stdc99 or -qlanglvl=extc99 options (or equivalent pragmas) or -qkeyword=restrict. The __restrict and __restrict__ keywords are recognized at all language levels. Related information v -qlanglvl and -qkeyword in the XL C Compiler Reference
tag_identifier
{ member_declaration_list } ;
where int_constant is a positive integer value indicating the byte-alignment boundary. The legal values are 1, 2, 4, 8, or 16. The following restrictions and limitations apply: v The __align qualifier cannot be used where the size of the variable alignment is smaller than the size of the type alignment. v Not all alignments may be representable in an object file. v The __align qualifier cannot be applied to the following: Individual elements within an aggregate definition. Individual elements of an array. Variables of incomplete type. Aggregates declared but not defined.
59
int __align(128) functionB( ); /* An error typedef int __align(128) T; __align enum C {a, b, c};
Applying __align to align and pad aggregate tags without affecting aggregate members:
__align(1024) struct structA {int i; int j;}; /* struct structA is aligned on a 1024-byte boundary with size including padding of 1024 bytes */ __align(1024) union unionA {int i; int j;}; /* union unionA is aligned on a 1024-byte boundary with size including padding of 1024 bytes */
Applying __align to a structure or union, where the size and alignment of the aggregate using the structure or union is affected:
__align(128) struct S {int i;}; struct S sarray[10]; struct S __align(64) svar; /* sizeof(struct S) == 128 */
/* sarray is aligned on 128-byte boundary with sizeof(sarray) == 1280 */ /* error - alignment of variable is smaller than alignment of type */
struct S2 {struct S s1; int a;} s2; /* s2 is aligned on 128-byte boundary with sizeof(s2) == 256 */
Applying __align where the size of the variable alignment differs from the size of the type alignment:
__align(64) struct S {int i;}; struct S __align(32) s1; /* error, alignment of variable is smaller
60
XL C Language Reference
than alignment of type struct S __align(128) s2; struct S __align(16) s3[10]; int __align(1) s4; __align(1) struct S {int i;}; /* s2 is aligned on 128-byte boundary /* error /* error /* error
*/ */ */ */ */
Related information v The aligned variable attribute on page 85 v The __alignof__ operator on page 107 v Aligning data in the XL C Programming Guide End of IBM extension
Type attributes
IBM extension Type attributes are language extensions provided to facilitate compilation of programs developed with the GNU C compiler compilers. These language features allow you to use named attributes to specify special properties of data objects. Type attributes apply to the definitions of user-defined types, such as structures, unions, enumerations, classes. Any variables that are declared as having that type will have the attribute applied to them. A type attribute is specified with the keyword __attribute__ followed by the attribute name and any additional arguments the attribute name requires. The __attribute__ specification is included in the definition of a user-defined type, and generally precedes the tag identifier. Although there are variations, the syntax of a type attribute is of the general form: Type attribute syntax
struct union enum __attribute__ (( attribute name __attribute name__ ))
{ member_definition_list } ; tag_identifier
The attribute name can be specified with or without double underscore characters leading and trailing; however, using the double underscore reduces the likelihood of a name conflict with a macro of the same name. For unsupported attribute names, the XL C compiler issues diagnostics and ignores the attribute specification. Multiple attribute names can be specified in the same attribute specification. The following type attributes are supported: v The aligned type attribute v The packed type attribute v The transparent_union type attribute (C only) Related information
Chapter 3. Data objects and declarations
61
The alignment_factor is the number of bytes, specified as a constant expression that evaluates to a positive power of 2.You can specify a value up to a maximum 1048576 bytes. If you omit the alignment factor (and its enclosing parentheses), the compiler automatically uses 16 bytes. If you specify an alignment factor greater than the maximum, the attribute specification is ignored, and the compiler simply uses the default alignment in effect. The alignment value that you specify will be applied to all instances of the type. Also, the alignment value applies to the variable as a whole; if the variable is an aggregate, the alignment value applies to the aggregate as a whole, not to the individual members of the aggregate. In all of the following examples, the aligned attribute is applied to the structure type A. Because a is declared as a variable of type A, it will also receive the alignment specification, as will any other instances declared of type A.
struct __attribute__((__aligned__(8))) A {}; struct __attribute__((__aligned__(8))) A {} a; typedef struct __attribute__((__aligned__(8))) A {} a;
Related information v The __align qualifier on page 59 v The aligned variable attribute on page 85 v The __alignof__ operator on page 107 v Aligning data in the XL C Programming Guide
62
XL C Language Reference
Unlike the aligned type attribute, the packed type attribute is not allowed in a typedef declaration. Related information v The __align qualifier on page 59 v The packed variable attribute on page 86 v The __alignof__ operator on page 107 v Aligning data in the XL C Programming Guide
The union must be a complete union type. The transparent_union type attribute can be applied to anonymous unions with tag names. When the transparent_union type attribute is applied to the outer union of a nested union, the size of the inner union (that is, its largest member) is used to determine if it has the same machine representation as the other members of the outer union. For example,
union __attribute__((__transparent_union__)) u_t { union u2_t { char a; short b; char c; char d; }; int a; } ;
the attribute is ignored because the first member of union u_t, which is itself a union, has a machine representation of 2 bytes, whereas the other member of union u_t is of type int, which has a machine representation of 4 bytes. The same rationale applies to members of a union that are structures. When a member of a union to which type attribute transparent_union has been applied is a struct, the machine representation of the entire struct is considered, rather than members. All members of the union must have the same machine representation as the first member of the union. This means that all members must be representable by the same amount memory as the first member of the union. The machine representation of the first member represents the maximum memory size for any
Chapter 3. Data objects and declarations
63
remaining union members. For instance, if the first member of a union to which type attribute transparent_union has been applied is of type int, then all following members must be representable by at most 4 bytes. Members that are representable by 1, 2, or 4 bytes are considered valid for this transparent union. Floating-point types (float, double, float _Complex, or double _Complex) types or vector types can be members of a transparent union, but they cannot be the first member. The restriction that all members of the transparent union have the same machine representation as the first member still applies. End of IBM extension
64
XL C Language Reference
Chapter 4. Declarators
This section continues the discussion of data declarations and includes the following topics: v Overview of declarators v Type names on page 66 v Pointers on page 68 v Arrays on page 70 v Initializers on page 73 v Variable attributes on page 83
Overview of declarators
A declarator designates a data object or function. A declarator can also include an initialization. Declarators appear in most data definitions and declarations and in some type definitions. For data declarations, a declarator has the form: Declarator syntax
direct_declarator initializer pointer_operator
Direct declarator:
declarator_name direct_declarator [ constant_expression
Pointer operator:
* &
type_qualifiers
Declarator name:
identifier
The type_qualifiers represent one or a combination of const and volatile. Initializers are discussed in Initializers on page 73. The following are known as derived declarator types, and are therefore discussed in this section: v Pointers
Copyright IBM Corp. 1998, 2005
65
v Arrays
IBM In addition, for compatibility with GNU C, XL C allows you to use variable attributes to modify the properties of data objects. As they are normally specified as part of the declarator in a declaration, they are described in this section, in Variable attributes on page 83.
Examples of declarators
The following table indicates the declarators within the declarations:
Declaration int owner; int *node; int names[126]; volatile int min; Declarator owner *node names[126] min Description owner is an integer data object. node is a pointer to an integer data object. names is an array of 126 integer elements. min is a volatile integer. volume is a volatile pointer to an integer. next is a pointer to a volatile integer. sequence is an array of five pointers to volatile integer data objects. clock is a constant and volatile integer with static storage duration and external linkage.
int * volatile volume; * volatile volume volatile int * next; volatile int * sequence[5]; extern const volatile int clock; *next *sequence[5] clock
Related information v Type qualifiers on page 56 v Array subscripting operator [ ] on page 100 v Function declarators on page 160
Type names
A data type, more precisely, a type name, is required in several contexts as something that you must specify without declaring an object; for example, when writing an explicit cast expression or when applying the sizeof operator to a type. Syntactically, the name of a data type is the same as a declaration of a function or object of that type, but without the identifier. To read or write a type name correctly, put an imaginary identifier within the syntax, splitting the type name into simpler components. For example, int is a type specifier, and it always appears to the left of the identifier in a declaration. An imaginary identifier is unnecessary in this simple case. However, int *[5] (an array of 5 pointers to int) is also the name of a type. The type specifier int *
66
XL C Language Reference
always appears to the left of the identifier, and the array subscripting operator always appears to the right. In this case, an imaginary identifier is helpful in distinguishing the type specifier. As a general rule, the identifier in a declaration always appears to the left of the subscripting and function call operators, and to the right of a type specifier, type qualifier, or indirection operator. Only the subscripting, function call, and indirection operators may appear in a type name declaration. They bind according to normal operator precedence, which is that the indirection operator is of lower precedence than either the subscripting or function call operators, which have equal ranking in the order of precedence. Parentheses may be used to control the binding of the indirection operator. It is possible to have a type name within a type name. For example, in a function type, the parameter type syntax nests within the function type name. The same rules of thumb still apply, recursively. The following constructions illustrate applications of the type naming rules.
Table 11. Type names Syntax int *[5] int (*)[5] int (*)[*] int *() int (*)(void) int (*const [])(unsigned int, ...) Description array of 5 pointers toint pointer to an array of 5 integers pointer to an variable length array of an unspecified number of integers function with no parameter specification returning a pointer to int function with no parameters returning an int array of an unspecified number of constant pointers to functions returning an int. Each function takes one parameter of type unsigned int and an unspecified number of other parameters.
The compiler turns any function designator into a pointer to the function. This behavior simplifies the syntax of function calls.
int foo(float); int (*p)(float); p=&foo; p=foo; /* /* /* /* foo is a function designator */ p is a pointer to a function */ legal, but redundant */ legal because the compiler turns foo into a function pointer */
Related information v Operator precedence and associativity on page 126 v Examples of expressions and precedence on page 128 v Parenthesized expressions ( ) on page 98
Chapter 4. Declarators
67
Pointers
A pointer type variable holds the address of a data object or a function. A pointer can refer to an object of any one data type; it cannot refer to a bit field or a reference. Some common uses for pointers are: v To access dynamic data structures such as linked lists, trees, and queues. v To access elements of an array or members of a structure. v To access an array of characters as a string. v To pass the address of a variable to a function. By referencing a variable through its address, a function can change the contents of that variable. Note that the placement of the type qualifiers volatile and const affects the semantics of a pointer declaration. If either of the qualifiers appears before the *, the declarator describes a pointer to a type-qualified object. If either of the qualifiers appears between the * and the identifier, the declarator describes a type-qualifed pointer. The following table provides examples of pointer declarations.
Table 12. Pointer declarations Declaration long *pcoat; extern short * const pvolt; extern int volatile *pnut; float * volatile psoup; enum bird *pfowl; char (*pvish)(void); Description pcoat is a pointer to an object having type long pvolt is a constant pointer to an object having type short pnut is a pointer to an int object having the volatile qualifier psoup is a volatile pointer to an object having type float pfowl is a pointer to an enumeration object of type bird pvish is a pointer to a function that takes no parameters and returns a char
Related information v Type qualifiers on page 56 v Initialization of pointers on page 80 v Compatibility of pointers (C only) on page 70 v Pointer conversions on page 92 v Address operator & on page 105 v Indirection operator * on page 106 v Pointers to functions on page 169
Pointer arithmetic
You can perform a limited number of arithmetic operations on pointers. These operations are: v Increment and decrement v Addition and subtraction
68
XL C Language Reference
v Comparison v Assignment The increment (++) operator increases the value of a pointer by the size of the data object the pointer refers to. For example, if the pointer refers to the second element in an array, the ++ makes the pointer refer to the third element in the array. The decrement (--) operator decreases the value of a pointer by the size of the data object the pointer refers to. For example, if the pointer refers to the second element in an array, the -- makes the pointer refer to the first element in the array. You can add an integer to a pointer but you cannot add a pointer to a pointer. If the pointer p points to the first element in an array, the following expression causes the pointer to point to the third element in the same array:
p = p + 2;
If you have two pointers that point to the same array, you can subtract one pointer from the other. This operation yields the number of elements in the array that separate the two addresses that the pointers refer to. You can compare two pointers with the following operators: ==, !=, <, >, <=, and >=. Pointer comparisons are defined only when the pointers point to elements of the same array. Pointer comparisons using the == and != operators can be performed even when the pointers point to elements of different arrays. You can assign to a pointer the address of a data object, the value of another compatible pointer or the NULL pointer. Related information v Increment operator ++ on page 103 v Arrays on page 70 v Decrement operator on page 104 v Chapter 6, Expressions and operators, on page 95
Type-based aliasing
The compiler follows the type-based aliasing rule in the C standard when the -qalias=ansi option is in effect (which it is by default). This rule, also known as the ANSI aliasing rule, states that a pointer can only be dereferenced to an object of the same type or a compatible type. 1The common coding practice of casting a
1. The C Standard states that an object shall have its stored value accessed only by an lvalue that has one of the following types: v the declared type of the object, v a qualified version of the declared type of the object, v a type that is the signed or unsigned type corresponding to the declared type of the object, v a type that is the signed or unsigned type corresponding to a qualified version of the declared type of the object, v an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or v a character type
Chapter 4. Declarators
69
pointer to an incompatible type and then dereferencing it violates this rule. (Note that char pointers are an exception to this rule.) The compiler uses the type-based aliasing information to perform optimizations to the generated code. Contravening the type-based aliasing rule can lead to unexpected behavior, as demonstrated in the following example:
int *p; double d = 0.0; int *faa(double *g); /* cast operator inside the function */
void foo(double f) { p = faa(&f); /* turning &f into a int ptr */ f += 1.0; /* compiler may discard this statement */ printf("f=%x\n", *p); } int *faa(double *g) { return (int*) g; } /* questionable cast; */ /* the function can be in */ /* another translation unit */
In the above printf statement, *p cannot be dereferenced to a double under the ANSI aliasing rule. The compiler determines that the result of f += 1.0; is never used subsequently. Thus, the optimizer may discard the statement from the generated code. If you compile the above example with optimization enabled, the printf statement may output 0 (zero). Related information v -qalias=ansi in the XL C Compiler Reference
The next example shows incompatible declarations for the assignment operation:
double league; int * minor; /* ... */ minor = &league;
/* error */
Arrays
An array is a collection of objects of the same data type, allocated contiguously in memory. Individual objects in an array, called elements, are accessed by their position in the array. The subscripting operator ([]) provides the mechanics for creating an index to array elements. This form of access is called indexing or
70
XL C Language Reference
subscripting. An array facilitates the coding of repetitive tasks by allowing the statements executed on each element to be put into a loop that iterates through each element in the array. The C language provides limited built-in support for an array type: reading and writing individual elements.Assignment of one array to another, the comparison of two arrays for equality, returning self-knowledge of size are not supported. The type of an array is derived from the type of its elements, in what is called array type derivation. If array objects are of incomplete type, the array type is also considered incomplete. Array elements may not be of type void or of function type. However, arrays of pointers to functions are allowed. The array declarator contains an identifier followed by an optional subscript declarator. An identifier preceded by an asterisk (*) is an array of pointers. Array subscript declarator syntax
constant_expression ]
The constant_expression is a constant integer expression, indicating the size of the array, which must be positive. If the declaration appears in block or function scope, a nonconstant expression can be specified for the array subscript declarator, and the array is considered a variable-length array, as described in Variable length arrays on page 72. The subscript declarator describes the number of dimensions in the array and the number of elements in each dimension. Each bracketed expression, or subscript, describes a different dimension and must be a constant expression. The following example defines a one-dimensional array that contains four elements having type char:
char list[4];
The first subscript of each dimension is 0. The array list contains the elements:
list[0] list[1] list[2] list[3]
The following example defines a two-dimensional array that contains six elements of type int:
int roster[3][2];
Multidimensional arrays are stored in row-major order. When elements are referred to in order of increasing storage location, the last subscript varies the fastest. For example, the elements of array roster are stored in the order:
Chapter 4. Declarators
71
You can leave the first (and only the first) set of subscript brackets empty in: v Array definitions that contain initializations v extern declarations v Parameter declarations In array definitions that leave the first set of subscript brackets empty, the initializer determines the number of elements in the first dimension. In a one-dimensional array, the number of initialized elements becomes the total number of elements. In a multidimensional array, the initializer is compared to the subscript declarator to determine the number of elements in the first dimension. Related information v Array subscripting operator [ ] on page 100 v Initialization of arrays on page 81
If the size of the array is indicated by * instead of an expression, the variable length array is considered to be of unspecified size. Such arrays are considered complete types, but can only be used in declarations of function prototype scope. A variable length array and a pointer to a variable length array are considered variably modified types. Declarations of variably modified types must be at either block scope or function prototype scope. Array objects declared with the extern storage class specifier cannot be of variable length array type. Array objects declared with the static storage class specifier can be a pointer to a variable length array, but not an actual variable length array. The identifiers declared with a variably modified type must be ordinary identifiers and therefore cannot be members of structures or unions. A variable length array cannot be initialized.
72
XL C Language Reference
A variable length array can be the operand of a sizeof expression. In this case, the operand is evaluated at run time, and the size is neither an integer constant nor a constant expression, even though the size of each instance of a variable array does not change during its lifetime. A variable length array can be used in a typedef expression. The typedef name will have only block scope. The length of the array is fixed when the typedef name is defined, not each time it is used. A function parameter can be a variable length array. The necessary size expressions must be provided in the function definition. The compiler evaluates the size expression of a variably modified parameter on entry to the function. For a function declared with a variable length array as a parameter, as in the following,
void f(int x, int a[][x]);
the size of the variable length array argument must match that of the function definition. Related information v Flexible array members on page 46
Compatibility of arrays
Two array types that are similarly qualified are compatible if the types of their elements are compatible. For example,
char ex1[25]; const char ex2[25];
are not compatible. The composite type of two compatible array types is an array with the composite element type. The sizes of both original types must be equivalent if they are known. If the size of only one of the original array types is known, then the composite type has that size. For example:
char ex3[]; char ex4[42];
The composite type of ex3 and ex4 is char[42]. If one of the original types is a variable length array, the composite type is that type. Related information v External linkage on page 6
Initializers
An initializer is an optional part of a data declaration that specifies an initial value of a data object. The initializers that are legal for a particular declaration depend on the type and storage class of the object to be initialized. The initializer consists of the = symbol followed by an initial expression or a brace-enclosed list of initial expressions separated by commas. Individual expressions must be separated by commas, and groups of expressions can be enclosed in braces and separated by commas. Braces ({ }) are optional if the initializer for a character string is a string literal. The number of initializers must not be greater than the number of elements to be initialized. The initial expression evaluates to the first value of the data object.
Chapter 4. Declarators
73
To assign a value to an arithmetic or pointer type, use the simple initializer: = expression. For example, the following data definition uses the initializer = 3 to set the initial value of group to 3:
int group = 3;
You initialize a variable of character type with a character literal (consisting of one character) or with an expression that evaluates to an integer. Initialization and storage classes discusses the rules for initialization according to the storage class of variables. Designated initializers for aggregate types (C only) on page 75 describes designated initializers, which are a C99 feature that can be used to initialize arrays, structures, and unions. The following sections discuss initializations for derived types: v Initialization of vectors on page 77 v Initialization of structures and unions on page 78 v Initialization of pointers on page 80 v Initialization of arrays on page 81
74
XL C Language Reference
v Appear as part of the definition and the initial value must be described by a constant expression; or v Reduce to the address of a previously declared object with static storage duration. You may modify this object with pointer arithmetic. (In other words, you may modify the object by adding or subtracting an integral constant expression.) If you do not explicitly initialize an extern variable, its initial value is zero of the appropriate type. Initialization of an extern object is completed by the time the program starts running. Related information v The extern storage class specifier on page 37
[ array subscript ]
= expression
Chapter 4. Declarators
75
In the following example, the designator is .any_member and the designated initializer is .any_member = 13:
union { /* ... */ } caw = { .any_member = 13 };
The following example shows how the second and third members b and c of structure variable klm are initialized with designated initializers:
struct xyz { int a; int b; int c; } klm = { .a = 99, .c = 100 };
In the following example, the third and second elements of the one-dimensional array aa are initialized to 3 and 6, respectively:
int aa[4] = { [2] = 3, [1] = 6 };
The following example initializes the first four and last four elements, while omitting the middle four:
static short grid[3] [4] = { [0][0]=8, [0][2]=4, [2][0]=9, [2][2]=1, [0][1]=6, [0][3]=1, [2][1]=3, [2][3]=1 };
Designated initializers can be combined with regular initializers, as in the following example:
int a[10] = {2, 4, [8]=9, 10}
In this example, a[0] is initialized to 2, a[1] is initialized to 4, a[2] to a[7] are initialized to 0, and a[9] is initialized to 10. In the following example, a single designator is used to allocate space from both ends of an array:
int a[MAX] = { 1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0 };
The designated initializer, [MAX-5] = 8, means that the array element at subscript MAX-5 should be initialized to the value 8. If MAX is 15, a[5] through a[9] will be initialized to zero. If MAX is 7, a[2] through a[4] will first have the values 5, 7, and 9, respectively, which are overridden by the values 8, 6, and 4. In other words, if MAX is 7, the initialization would be the same as if the declaration had been written:
76
XL C Language Reference
int a[MAX] = { 1, 3, 8, 6, 4, 2, 0 };
You can also use designators to represent members of nested structures. For example:
struct a { struct b { int c; int d; } e; float f; } g = {.e.c = 3 };
initializes member c of structure variable e, which is a member of structure variable g, to the value of 3. Related information v Initialization of structures and unions on page 78 v Initialization of arrays on page 81
Initialization of vectors
IBM extension A vector type is initialized by a vector literal or any expression having the same vector type. For example:
vector unsigned int v1; vector unsigned int v2 = (vector unsigned int)(10); v1 = v2;
XL C extends the AltiVec specification to allow a vector type to be initialized by an initializer list. This feature is an extension for compatibility with GNU C. Vector initializer list syntax
, vector_type identifier = { initializer } ;
The number of values in a braced initializer list must be less than or equal to the number of elements of the vector type. Any uninitialized element will be initialized to zero. The following are examples of vector initialization using initializer lists:
vector unsigned int v1 = {1}; // initialize the first 4 bytes of v1 with 1 // and the remaining 12 bytes with zeros // initialize the first 8 bytes of v2 with 1 and 2 // and the remaining 8 bytes with zeros // equivalent to the vector literal // (vector unsigned int) (1,2,3,4)
Unlike vector literals, the values in the initializer list do not have to be constant expressions unless the initialized vector variable has static duration. Thus, the following is legal:
Chapter 4. Declarators
77
int i=1; int foo() { return 2; } int main() { vector unsigned int v1 = {i, foo()}; return 0; }
Using C89-style initialization, the following example shows how you would initialize the first union member birthday of the union variable people:
union { char birthday[9]; int age; float weight; } people = {"23/07/57"};
Using a designated initializer in the same example, the following initializes the second union member age :
union { char birthday[9]; int age; float weight; } people = { .age = 14 };
78
XL C Language Reference
Unnamed structure or union members do not participate in initialization and have indeterminate value after initialization. Therefore, in the following example, the bit field is not initialized, and the initializer 3 is applied to member b:
struct { int int int } w a; :10; b; = { 2, 3 };
You do not have to initialize all members of a structure or union; the initial value of uninitialized structure members depends on the storage class associated with the structure or union variable. In a structure declared as static, any members that are not initialized are implicitly initialized to zero of the appropriate type; the members of a structure with automatic storage have no default initialization. The default initializer for a union with static storage is the default for the first component; a union with automatic storage has no default initialization. The following definition shows a partially initialized structure:
struct address { int street_no; char *street_name; char *city; char *prov; char *postal_code; }; struct address temp_address = { 44, "Knyvet Ave.", "Hamilton", "Ontario" };
To initialize only the third and fourth members of the temp_address variable, you could use a designated initializer list, as follows:
struct address { int street_no; char *street_name;
Chapter 4. Declarators
79
char *city; char *prov; char *postal_code; }; struct address temp_address = { .city = "Hamilton", .prov = "Ontario" };
Related information v Structure and union variable declarations on page 49 v Assignment expressions on page 123
Initialization of enumerations
The initializer for an enumeration variable contains the = symbol followed by an expression enumeration_constant. The first line of the following example declares the enumeration grain. The second line defines the variable g_food and gives g_food the initial value of barley (2).
enum grain { oats, wheat, barley, corn, rice }; enum grain g_food = barley;
Initialization of pointers
The initializer is an = (equal sign) followed by the expression that represents the address that the pointer is to contain. The following example defines the variables time and speed as having type double and amount as having type pointer to a double. The pointer amount is initialized to point to total:
double total, speed, *amount = &total;
The compiler converts an unsubscripted array name to a pointer to the first element in the array. You can assign the address of the first element of an array to a pointer by specifying the name of the array. The following two sets of definitions are equivalent. Both define the pointer student and initialize student to the address of the first element in section:
int section[80]; int *student = section;
is equivalent to:
int section[80]; int *student = §ion[0];
You can assign the address of the first character in a string constant to a pointer by specifying the string constant in the initializer. The following example defines the pointer variable string and the string constant "abcd". The pointer string is initialized to point to the character a in the string "abcd".
char *string = "abcd";
The following example defines weekdays as an array of pointers to string constants. Each element points to a different string. The pointer weekdays[2], for example, points to the string "Tuesday".
80
XL C Language Reference
static char *weekdays[ ] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
A pointer can also be initialized to null using any integer constant expression that evaluates to 0, for example char * a=0;. Such a pointer is a null pointer. It does not point to any object. Related information v Pointers on page 68
Initialization of arrays
The initializer for an array is a comma-separated list of constant expressions enclosed in braces ({ }). The initializer is preceded by an equal sign (=). You do not need to initialize all elements in an array. If an array is partially initialized, elements that are not initialized receive the value 0 of the appropriate type. The same applies to elements of arrays with static storage duration. (All file-scope variables and function-scope variables declared with the static keyword have static storage duration.) There are two ways to specify initializers for arrays: v With C89-style initializers, array elements must be initialized in subscript order. v Using designated initializers, which allow you to specify the values of the subscript elements to be initialized, array elements can be initialized in any order. Designated initializers are described in detail in Designated initializers for aggregate types (C only) on page 75. Using C89-style initializers, the following definition shows a completely initialized one-dimensional array:
static int number[3] = { 5, 7, 2 };
The array number contains the following values: number[0] is 5, number[1] is 7; number[2] is 2. When you have an expression in the subscript declarator defining the number of elements (in this case 3), you cannot have more initializers than the number of elements in the array. The following definition shows a partially initialized one-dimensional array:
static int number1[3] = { 5, 7 };
The values of number1[0] and number1[1] are the same as in the previous definition, but number1[2] is 0. The following definition shows how you can use designated initializers to skip over elements of the array that you dont want to initialize explicitly:
static int number[3] = { [0] = 5, [2] = 7 };
The array number contains the following values: number[0] is 5; number[1] is implicitly initialized to 0; number[2] is 7. Instead of an expression in the subscript declarator defining the number of elements, the following one-dimensional array definition defines one element for each initializer specified:
static int item[ ] = { 1, 2, 3, 4, 5 };
Chapter 4. Declarators
81
The compiler gives item the five initialized elements, because no size was specified and there are five initializers.
Note that the following definition would result in the null character being lost:
static char name3[3]="Jan";
v Using braces to group the values of the elements you want initialized. You can put braces around each element, or around any nesting level of elements. The following definition contains two elements in the first dimension (you can consider these elements as rows). The initialization contains braces around each of these two elements:
static int month_days[2][12] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
v Using nested braces to initialize dimensions and elements in a dimension selectively. In the following example, only the first eight elements of the array
82
XL C Language Reference
grid are explicitly initialized. The remaining four elements that are not explicitly initialized are automatically initialized to zero.
static short grid[3] [4] = {8, 6, 4, 1, 9, 3, 1, 1};
Using designated initializers. The following example uses designated initializers to explicitly initialize only the last four elements of the array. The first eight elements that are not explicitly initialized are automatically initialized to zero.
static short grid[3] [4] = { [2][0] = 8, [2][1] = 6, [2][2] = 4, [2][3] = 1 };
Related information v Arrays on page 70 v Designated initializers for aggregate types (C only) on page 75
Variable attributes
IBM extension Variable attributes are language extensions provided to facilitate the compilation of programs developed with the GNU C compiler compilers. These language features allow you to use named attributes to specify special properties of data objects. Variable attributes apply to the declarations of simple variables, aggregates, and member variables of aggregates. A variable attribute is specified with the keyword __attribute__ followed by the attribute name and any additional arguments the attribute name requires. A
Chapter 4. Declarators
83
variable __attribute__ specification is included in the declaration of a variable, and can be placed before or after the declarator. Although there are variations, the syntax generally takes either of the following forms: Variable attribute syntax: post-declarator
, declarator __attribute__ (( attribute name __attribute name__ ))
declarator initializer
The attribute name can be specified with or without leading and trailing double underscore characters; however, using the double underscore reduces the likelihood of a name conflict with a macro of the same name. For unsupported attribute names, the XL C compiler issues diagnostics and ignores the attribute specification. Multiple attribute names can be specified in the same attribute specification. In a comma-separated list of declarators on a single declaration line, if a variable attribute appears before all the declarators, it applies to all declarators in the declaration. If the attribute appears after a declarator, it only applies to the immediately preceding declarator. For example:
struct A { /* typical placement of variable attribute */ /* variable attribute can also be placed here */ /* /* /* attribute applies to f only attribute applies to g only */ */ */
int b __attribute__((aligned)); int __attribute__((aligned))__ c = 10; int d, e, f __attribute__((aligned)); int g __attribute__((aligned)), h, i; int __attribute__((aligned)) j, k, l; };
The following variable attributes are supported: v The aligned variable attribute v The packed variable attribute v The mode variable attribute v The weak variable attribute Related information v Type attributes on page 61
84
XL C Language Reference
The alignment_factor is the number of bytes, specified as a constant expression that evaluates to a positive power of 2. You can specify a value up to a maximum of 1048576 bytes. If you omit the alignment factor (and its enclosing parentheses the compiler automatically uses 16 bytes. If you specify an alignment factor greater than the maximum, the attribute specification is ignored, and the compiler simply uses the default alignment in effect. When you apply the aligned attribute to a bit field structure member variable, the attribute specification is applied to the bit field container. If the default alignment of the container is greater than the alignment factor, the default alignment is used. In the following example, the structures first_address and second_address are set to an alignment of 16 bytes:
struct address { int street_no; char *street_name; char *city; char *prov; char *postal_code; } first_address __attribute__((__aligned__(16))) ; struct address second_address __attribute__((__aligned__(16))) ;
In the following example, only the members first_address.prov and first_address.postal_code are set to an alignment of 16 bytes:
struct address { int street_no; char *street_name; char *city; char *prov __attribute__((__aligned__(16))) ; char *postal_code __attribute__((__aligned__(16))) ; } first_address ;
Related information v The __align qualifier on page 59 v Aligning data in the XL C Programming Guide v The __alignof__ operator on page 107 v The aligned type attribute on page 62
Chapter 4. Declarators
85
Related information v The __align qualifier on page 59 v Aligning data in the XL C Programming Guide v The __alignof__ operator on page 107 v The packed type attribute on page 62
The valid argument for the mode is any of the of the following type specifiers that indicates a specific width: v byte means a 1-byte integer type v word means a 4-byte integer type v pointer means 4-byte integer type in 32-bit mode and an 8-byte integer type in 64-bit mode
86
XL C Language Reference
Chapter 4. Declarators
87
88
XL C Language Reference
Integral conversions
Unsigned integer to unsigned integer or signed integer to signed integer If the types are identical, there is no change. If the types are of a different
Copyright IBM Corp. 1998, 2005
89
size, and the value can be represented by the new type, the value is not changed; if the value cannot be represented by the new type, truncation or sign shifting will occur. Signed integer to unsigned integer The resulting value is the smallest unsigned integer type congruent to the source integer. If the value cannot be represented by the new type, truncation or sign shifting will occur. Unsigned integer to signed integer If the signed type is large enough to hold the original value, there is no change. If the value can be represented by the new type, the value is not changed; if the value cannot be represented by the new type, truncation or sign shifting will occur. Signed and unsigned character types to integer If the original value can be represented by int, it is represented as int. If the value cannot be represented by int, it is promoted to unsigned int. Wide character type wchar_t to integer If the original value can be represented by int, it is represented as int. If the value cannot be represented by int, it is promoted to the smallest type that can hold it: unsigned int, long, or unsigned long. Signed and unsigned integer bit field to integer If the original value can be represented by int, it is represented as int. If The value cannot be represented by int, it is promoted to unsigned int. Enumeration type to integer If the original value can be represented by int, it is represented as int. If the value cannot be represented by int, it is promoted to the smallest type that can hold it: unsigned int, long, or unsigned long. Note that an enumerated type can be converted to an integral type, but an integral type cannot be converted to an enumeration.
Boolean conversions
Boolean to integer C If the Boolean value is 0, the result is an int with a value of 0. If the Boolean value is 1, the result is an int with a value of 1. Scalar to Boolean C If the scalar value is equal to 0, the Boolean value is 0; otherwise the Boolean value is 1.
Floating-point conversions
Real to real or complex to complex If the types are identical, there is no change. If the types are of a different size, and the value can be represented by the new type, the value is not changed; if the value cannot be represented by the new type, rounding and loss of precision will occur. Complex to real The imaginary part of the complex value is discarded. The value of the real part is converted according to the real to real rule given above. Real to complex The value of the real part is converted according to the real to real rule given above. The value of the imaginary part is zero.
90
XL C Language Reference
Notes: 1. If one operand has unsigned int type and the other operand has long int type but the value of the unsigned int cannot be represented in a long int, both operands are converted to unsigned long int. Related information v Integral types on page 39 v Boolean types on page 40 v Floating-point types on page 41 v Character types on page 41 v Enumerations on page 51 v Binary expressions on page 113
91
Lvalue-to-rvalue conversions
If an lvalue appears in a situation in which the compiler expects an rvalue, the compiler converts the lvalue to an rvalue. The following table lists exceptions to this:
Situation before conversion The lvalue is a function type. The lvalue is an array. The type of the lvalue is an incomplete type. compile-time error The lvalue refers to an uninitialized object. undefined behavior Resulting behavior
The lvalue refers to an object not of the type undefined behavior of the rvalue, nor of a type derived from the type of the rvalue.
Pointer conversions
Pointer conversions are performed when pointers are used, including pointer assignment, initialization, and comparison. Conversions that involve pointers must use an explicit type cast. The exceptions to this rule are the allowable assignment conversions for C pointers. In the following table, a const-qualified lvalue cannot be used as a left operand of the assignment.
Table 15. Legal assignment conversions for C pointers Left operand type pointer to (object) T Permitted right operand types v the constant 0 v a pointer to a type compatible with T v a pointer to void (void*) pointer to (function) F v the constant 0 v a pointer to a function compatible with F
The referenced type of the left operand must have the same qualifiers as the right operand. An object pointer may be an incomplete type if the other pointer has type void*. Zero constant to null pointer A constant expression that evaluates to zero is a null pointer constant. This expression can be converted to a pointer. This pointer will be a null pointer (pointer with a zero value), and is guaranteed not to point to any object. Array to pointer An lvalue or rvalue with type array of N, where N is the type of a single element of the array, to N*. The result is a pointer to the initial element of the array. A conversion cannot be performed if the expression is used as the operand of the & (address) operator or the sizeof operator. Function to pointer
92
XL C Language Reference
An lvalue that is a function can be converted to an rvalue that is a pointer to a function of the same type, except when the expression is used as the operand of the & (address) operator, the () (function call) operator, or the sizeof operator. Related information v Pointers on page 68 v Integer constant expressions on page 98 v Arrays on page 70 v Pointers to functions on page 169
Conversion to void*
C pointers are not necessarily the same size as type int. Pointer arguments given to functions should be explicitly cast to ensure that the correct type expected by the function is being passed. The generic object pointer in C is void*, but there is no generic function pointer. Any pointer to an object, optionally type-qualified, can be converted to void*, keeping the same const or volatile qualifications. The allowable assignment conversions involving void* as the left operand are shown in the following table.
Table 16. Legal assignment conversions in C for void* Left operand type (void*) Permitted right operand types v The constant 0. v A pointer to an object. The object may be of incomplete type. v (void*)
If no function declaration is visible when a function is called, or when an expression appears as an argument in the variable part of a prototype argument
93
list, the compiler performs default argument promotions or converts the value of the expression before passing any arguments to the function. The automatic conversions consist of the following: v Integral and floating-point values are promoted. v Arrays or functions are converted to pointers. Related information v Integral and floating-point promotions on page 91 v The transparent_union type attribute (C only) on page 63 v Function call operator ( ) on page 99 v Function calls on page 168
94
XL C Language Reference
95
Certain operators require lvalues for some of their operands. The table below lists these operators and additional constraints on their usage.
Operator & (unary) ++ -= += -= *= %= <<= >>= &= ^= |= Requirement Operand must be an lvalue. Operand must be an lvalue. This applies to both prefix and postfix forms. Left operand must be an lvalue.
For example, all assignment operators evaluate their right operand and assign that value to their left operand. The left operand must be a modifiable lvalue or a reference to a modifiable object. The address operator (&) requires an lvalue as an operand while the increment (++) and the decrement (--) operators require a modifiable lvalue as an operand. The following example shows expressions and their corresponding lvalues.
Expression x = 42 *ptr = newvalue a++ Lvalue x *ptr a
IBM extension When compiled with the GNU C language extensions enabled, compound expressions, conditional expressions, and casts are allowed as lvalues, provided that their operands are lvalues. A compound expression can be assigned if the last expression in the sequence is an lvalue. The following expressions are equivalent:
(x + 1, y) *= 42; x + 1, (y *=42);
The address operator can be applied to a compound expression, provided the last expression in the sequence is an lvalue. The following expressions are equivalent:
&(x + 1, y); x + 1, &y;
A conditional expression can be a valid lvalue if its type is not void and both of its branches for true and false are valid lvalues. Casts are valid lvalues if the operand is an lvalue. The primary restriction is that you cannot take the address of an lvalue cast. End of IBM extension Related information v Arrays on page 70 v Lvalue-to-rvalue conversions on page 92
96
XL C Language Reference
Primary expressions
Primary expressions fall into the following general categories: v Names (identifiers) v Literals (constants) v Integer constant expressions v Parenthesized expressions ( )
Names
The value of a name depends on its type, which is determined by how that name is declared. The following table shows whether a name is an lvalue expression.
Table 17. Primary expressions: Names Name declared as Variable of arithmetic, pointer, enumeration, structure, or union type Enumeration constant Array Evaluates to An object of that type Is an lvalue? yes
no
That array. In contexts subject no to conversions, a pointer to the first object in the array, except where the name is used as the argument to the sizeof operator. That function. In contexts subject to conversions, a pointer to that function, except where the name is used as the argument to the sizeof operator, or as the function in a function call expression. no
Function
As an expression, a name may not refer to a label, typedef name, structure member, union member, structure tag, union tag, or enumeration tag. Names used for these purposes reside in a namespace that is separate from that of names used in expressions. However, some of these names may be referred to within expressions by means of special constructs: for example, the dot or arrow operators may be used to refer to structure and union members; typedef names may be used in casts or as an argument to the sizeof operator.
Literals
A literal is a numeric constant or string literal. When a literal is evaluated as an expression, its value is a constant. A lexical constant is never an lvalue. However, a string literal is an lvalue. Related information v Literals on page 11
97
Parenthesized expressions ( )
Use parentheses to explicitly force the order of expression evaluation. The following expression does not use parentheses to group operands and operators. The parentheses surrounding weight, zipcode are used to form a function call. Note how the compiler groups the operands and operators in the expression according to the rules for operator precedence and associativity:
expression
+
function call
*
unary minus
parameters
expression item
expression
- discount
handling
weight
zipcode
The following expression is similar to the previous expression, but it contains parentheses that change how the operands and operators are grouped:
98
XL C Language Reference
expression
*
parenthesized expression
expression
+
expression function call
parameters
unary minus
expression ( item
expression
- discount
handling
weight
zipcode
In an expression that contains both associative and commutative operators, you can use parentheses to specify the grouping of operands with operators. The parentheses in the following expression guarantee the order of grouping operands with the operators:
x = f + (g + h);
Postfix expressions
Postfix operators are operators that appear after their operands. A postfix expression is a primary expression, or a primary expression that contains a postfix operator. The available postfix operators are: v Function call operator ( ) v Array subscripting operator [ ] v Dot operator . v Arrow operator > v Compound literals The ranking, precendence and associativity rules for the postfix operators are summarized in Table 19 on page 126.
99
The type of a function call expression is the return type of the function. This type can either be a complete type or the type void. A function call expression is always an rvalue. Here are some examples of the function call operator:
stub() overdue(account, date, amount) notify(name, date + 5) report(error, time, date, ++num)
The order of evaluation for function call arguments is not specified. In the following example:
method(sample1, batch.process--, batch.process);
the argument batch.process-- might be evaluated last, causing the last two arguments to be passed with the same value. Related information v Function argument conversions on page 93 v Function calls on page 168
The first element of each array has the subscript 0. The expression contract[35] refers to the 36th element in the array contract. In a multidimensional array, you can reference each element (in the order of increasing storage locations) by incrementing the right-most subscript most frequently. For example, the following statement gives the value 100 to each element in the array code[4][3][6]:
100
XL C Language Reference
for (first = 0; first < 4; ++first) { for (second = 0; second < 3; ++second) { for (third = 0; third < 6; ++third) { code[first][second][third] = 100; } } }
C99 allows array subscripting on arrays that are not lvalues. However, using the address of a non-lvalue as an array subscript is still not allowed. The following example is valid in C99:
struct trio{int a[3];}; struct trio f(); foo (int index) { return f().a[index]; }
Related information v Pointers on page 68 v v v v Integral types on page 39 Lvalues and rvalues on page 95 Arrays on page 70 Pointer arithmetic on page 68
Dot operator .
The . (dot) operator is used to access structure, or union members. The member is specified by a postfix expression, followed by a . (dot) operator, followed by a possibly qualified identifier . The postfix expression must be an object of type struct or union. The name must be a member of that object. The value of the expression is the value of the selected member. If the postfix expression and the name are lvalues, the expression value is also an lvalue. If the postfix expression is type-qualified, the same type qualifiers will apply to the designated member in the resulting expression. Related information v Access to structure and union members on page 50
101
Compound literals
A compound literal is a postfix expression that provides an unnamed object whose value is given by an initializer list. The C99 language feature allows you to pass parameters to functions without the need for temporary variables. It is useful for specifying constants of an aggregate type (arrays, structures, and unions) when only one instance of such types is needed. The syntax for a compound literal resembles that of a cast expression. However, a compound literal is an lvalue, while the result of a cast expression is not. Furthermore, a cast can only convert to scalar types or void, whereas a compound literal results in an object of the specified type. Compound literal syntax
, ( type_name ) { initializer_list }
The type_name can be any data type, including vectors, and user-defined types. It can be an array of unknown size, but not a variable length array. If the type is an array of unknown size, the size is determined by the initializer list. The following example passes a constant structure variable of type point containing two integer members to the function drawline:
drawline((struct point){6,7});
If the compound literal occurs outside the body of a function, the initializer list must consist of constant expressions, and the unnamed object has static storage duration. If the compound literal occurs within the body of a function, the initializer list need not consist of constant expressions, and the unnamed object has automatic storage duration. For compatibility with GNU C, a static variable can be initialized with a compound literal of the same type, provided that all the initializers in the initializer list are constant expressions.
IBM
Unary expressions
A unary expression contains one operand and a unary operator. The supported standard unary operators are: v Increment operator ++ v Decrement operator v Unary plus operator + v Unary minus operator v Logical negation operator !
102
XL C Language Reference
alignof typeof Label value operator && _Pragma __real__ and __imag__
v v v v
IBM IBM
C
IBM
All unary operators have the same precedence and have right-to-left associativity, as shown in Table 20 on page 127. As indicated in the descriptions of the operators, the usual arithmetic conversions are performed on the operands of most unary expressions. Related information v Pointer arithmetic on page 68 v Lvalues and rvalues on page 95 v Arithmetic conversions and promotions on page 89
Increment operator ++
The ++ (increment) operator adds 1 to the value of a scalar operand, or if the operand is a pointer, increments the operand by the size of the object to which it points. The operand receives the result of the increment operation. The operand must be a modifiable lvalue of arithmetic or pointer type. You can put the ++ before or after the operand. If it appears before the operand, the operand is incremented. The incremented value is then used in the expression. If you put the ++ after the operand, the value of the operand is used in the expression before the operand is incremented. For example:
play = ++play1 + play2++;
The result has the same type as the operand after integral promotion. The usual arithmetic conversions on the operand are performed. IBM extension The increment operator has been extended to handle complex types. The operator works in the same manner as it does on a real type, except that only the real part
103
of the operand is incremented, and the imaginary part is unchanged. End of IBM extension
Decrement operator
The -- (decrement) operator subtracts 1 from the value of a scalar operand, or if the operand is a pointer, decreases the operand by the size of the object to which it points. The operand receives the result of the decrement operation. The operand must be a modifiable lvalue. You can put the -- before or after the operand. If it appears before the operand, the operand is decremented, and the decremented value is used in the expression. If the -- appears after the operand, the current value of the operand is used in the expression and the operand is decremented. For example:
play = --play1 + play2--;
The result has the same type as the operand after integral promotion, but is not an lvalue. The usual arithmetic conversions are performed on the operand. IBM extension The decrement operator has been extended to handle complex types, for compatibility with GNU C. The operator works in the same manner as it does on a real type, except that only the real part of the operand is decremented, and the imaginary part is unchanged. End of IBM extension
104
XL C Language Reference
The result has the same type as the operand after integral promotion. Note: Any minus sign in front of a constant is not part of the constant.
The expression ~x yields the following result (represented here as a 16-bit binary number):
1111111111111010
Note that the ~ character can be represented by the trigraph ??-. The 16-bit binary representation of ~0 is:
1111111111111111
IBM extension The bitwise negation operator has been extended to handle complex types. With a complex type, the operator computes the complex conjugate of the operand by reversing the sign of the imaginary part. End of IBM extension Related information v Trigraph sequences on page 26
105
If the operand is an lvalue or function, the resulting type is a pointer to the expression type. For example, if the expression has type int, the result is a pointer to an object having type int. If the operand is a qualified name and the member is not static, the result is a pointer to a member of class and has the same type as the member. The result is not an lvalue. If p_to_y is defined as a pointer to an int and y as an int, the following expression assigns the address of the variable y to the pointer p_to_y :
p_to_y = &y;
IBM extension The address operator has been extended to handle vector types, provided that VMX support is enabled. The result of the address operator applied to a vector type can be stored in a pointer to a compatible vector type. The address of a vector type can be used to initialize a pointer to vector type if both sides of the initialization have compatible types. A pointer to void can also be initialized with the address of a vector type. End of IBM extension The address of a label can be taken using the GNU C address operator &&. The label can thus be used as a value.
IBM
Indirection operator *
The * (indirection) operator determines the value referred to by the pointer-type operand. The operand cannot be a pointer to an incomplete type. If the operand points to an object, the operation yields an lvalue referring to that object. If the operand points to a function, the result is a function designator. Arrays and functions are converted to pointers. The type of the operand determines the type of the result. For example, if the operand is a pointer to an int, the result has type int. Do not apply the indirection operator to any pointer that contains an address that is not valid, such as NULL. The result is not defined. If p_to_y is defined as a pointer to an int and y as an int, the expressions:
p_to_y = &y; *p_to_y = 3;
106
XL C Language Reference
v Pointers on page 68
If type-id is a reference or a referenced type, the result is the alignment of the referenced type. If type-id is an array, the result is the alignment of the array element type. If type-id is a fundamental type, the result is implementation-defined. For example, on AIX, __alignof__(wchar_t) returns 2 for a 32-bit target, and 4 for a 64-bit target. The operand of __alignof__ can be a vector type, provided that VMX support is enabled. For example,
vector unsigned int v1 = (vector unsigned int)(10); vector unsigned int *pv1 = &v1; __alignof__(v1); // vector type alignment: 16. __alignof__(&v1); // address of vector alignment: 4. __alignof__(*pv1); // dereferenced pointer to vector alignment: 16. __alignof__(pv1); // pointer to vector alignment: 4. __alignof__(vector signed char); // vector type alignment: 16.
When __attribute__((aligned)) is used to increase the alignment of a variable of vector type, the value returned by the __alignof__ operator is the alignment factor specified by __attribute__((aligned)). Related information v The aligned variable attribute on page 85 End of IBM extension
107
The result for either kind of operand is not an lvalue, but a constant integer value. The type of the result is the unsigned integral type size_t defined in the header file stddef.h. Except in preprocessor directives, you can use a sizeof expression wherever an integral constant is required. One of the most common uses for the sizeof operator is to determine the size of objects that are referred to during storage allocation, input, and output functions. Another use of sizeof is in porting code across platforms. You can use the sizeof operator to determine the size that a data type represents. For example:
sizeof(int);
The sizeof operator applied to a type name yields the amount of memory that would be used by an object of that type, including any internal or trailing padding. IBM extension The operand of the sizeof operator can be a vector type or the result of dereferencing a pointer to vector type, provided that VMX support is enabled. In these cases, the return value of sizeof is always 16.
vector bool int v1; vector bool int *pv1 = &v1; sizeof(v1); // vector type: 16. sizeof(&v1); // address of vector: 4. sizeof(*pv1); // dereferenced pointer to vector: 16. sizeof(pv1); // pointer to vector: 4. sizeof(vector bool int); // vector type: 16.
The sizeof operator may not be applied to: v A bit field v A function type v An undefined structure or class v An incomplete type (such as void)
108
XL C Language Reference
The sizeof operator applied to an expression yields the same result as if it had been applied to only the name of the type of the expression. At compile time, the compiler analyzes the expression to determine its type. None of the usual type conversions that occur in the type analysis of the expression are directly attributable to the sizeof operator. However, if the operand contains operators that perform conversions, the compiler does take these conversions into consideration in determining the type. For example, the second line of the following sample causes the usual arithmetic conversions to be performed. Assuming that a short uses 2 bytes of storage and an int uses 4 bytes,
short x; ... sizeof (x) short x; ... sizeof (x + 1) /* the value of sizeof operator is 2 */ /* value is 4, result of addition is type int */
The result of the expression x + 1 has type int and is equivalent to sizeof(int). The value is also 4 if x has type char, short, or int or any enumeration type. Related information v Type names on page 66 v Integer constant expressions on page 98 v Arrays on page 70
A typeof construct itself is not an expression, but the name of a type. A typeof construct behaves like a type name defined using typedef, although the syntax resembles that of sizeof. The following examples illustrate its basic syntax. For an expression e:
int e; __typeof__(e + 1) j; /* the same as declaring int j; */ e = (__typeof__(e)) f; /* the same as casting e = (int) f; */
109
The behavior of the code is as if you had declared int a[2];. For a bit field, typeof represents the underlying type of the bit field. For example, int m:2;, the typeof(m) is int. Since the bit field property is not reserved, n in typeof(m) n; is the same as int n, but not int n:2. The typeof operator can be nested inside sizeof and itself. The following declarations of arr as an array of pointers to int are equivalent:
int *arr[10]; /* traditional C declaration __typeof__(__typeof__ (int *)[10]) a; /* equivalent declaration */ */
The typeof operator can be useful in macro definitions where expression e is a parameter. For example,
#define SWAP(a,b) { __typeof__(a) temp; temp = a; a = b; b = temp; }
Related information v Type names on page 66 v typedef definitions on page 54 End of IBM extension
The string_literal may be prefixed with L, making it a wide-string literal. The string literal is destringized and tokenized. The resulting sequence of tokens is processed as if it appeared in a pragma directive. For example:
_Pragma ( "pack(full)" )
would be equivalent to
#pragma pack(full)
110
XL C Language Reference
Related information v Pragma directives on page 188 v General Purpose Pragmas in the XL C Compiler Reference
The var_identifier is the name of a previously declared complex variable. The __real__ operator returns the real part of the complex variable, while the __imag__ operator returns the imaginary part of the variable. If the operand of these operators is an lvalue, the resulting expression can be used in any context where lvalues are allowed. They are especially useful in initializations of complex variables, and as arguments to calls to library functions such as printf and scanf that have no format specifiers for complex types. For example:
float _Complex myvar; __imag__(myvar) = 2.0f; __real__(myvar) = 3.0f;
initializes the imaginary part of the complex variable myvar to 2.0i and the real part to 3.0, and
printf("myvar = %f + %f * i\n", __real__(myvar), __imag__(myvar));
prints:
myvar = 2.000000 + 3.000000 * i
Related information v Complex literals on page 16 v Complex floating-point types on page 41 End of IBM extension
Cast expressions
The cast operator is used for explicit type conversions. It converts the value of an expression to a specified type. Cast expression syntax
( type ) expression
111
The following demonstrates the use of the cast operator to dynamically create an integer array of size 10:
#include <stdlib.h> int main(void) { int* myArray = (int*) malloc(10 * sizeof(int)); free(myArray); return 0; }
The malloc library function returns a void pointer that points to memory that will hold an object of the size of its argument. The statement int* myArray = (int*) malloc(10 * sizeof(int)) does the following: v Creates a void pointer that points to memory that can hold ten integers. v Converts that void pointer into an integer pointer with the use of the cast operator. v Assigns that integer pointer to myArray. Because a name of an array is the same as a pointer to the initial element of the array, myArray is an array of ten integers stored in the memory created by the call to malloc(). Related information v Type names on page 66 v Lvalues and rvalues on page 95
112
XL C Language Reference
A union cast is also valid as a function argument, part of a constant expression for initialization, and in a compound literal statement. Related information v Structures and unions on page 44 v The transparent_union type attribute (C only) on page 63 End of IBM extension
Binary expressions
A binary expression contains two operands separated by one operator. The supported binary operators are: v Multiplication operator * v Division operator / v Remainder operator % v Addition operator + v Subtraction operator v Bitwise left and right shift operators << >> v Relational operators < > <= >= v Equality and inequality operators == != v Bitwise AND operator & v Bitwise exclusive OR operator ^ v Bitwise inclusive OR operator | v Logical AND operator && v Logical OR operator || All binary operators have left-to-right associativity, but not all binary operators have the same precedence. The ranking and precedence rules for binary operators is summarized in Table 21 on page 127. The order in which the operands of most binary operators are evaluated is not specified. To ensure correct results, avoid creating binary expressions that depend on the order in which the compiler evaluates the operands. As indicated in the descriptions of the operators, the usual arithmetic conversions are performed on the operands of most binary expressions. Related information v Lvalues and rvalues on page 95 v Arithmetic conversions and promotions on page 89
Multiplication operator *
The * (multiplication) operator yields the product of its operands. The operands must have an arithmetic or enumeration type. The result is not an lvalue. The usual arithmetic conversions on the operands are performed.
113
Because the multiplication operator has both associative and commutative properties, the compiler can rearrange the operands in an expression that contains more than one multiplication operator. For example, the expression:
sites * number * cost
Division operator /
The / (division) operator yields the algebraic quotient of its operands. If both operands are integers, any fractional part (remainder) is discarded. Throwing away the fractional part is often called truncation toward zero. The operands must have an arithmetic or enumeration type. The right operand may not be zero: the result is undefined if the right operand evaluates to 0. For example, expression 7 / 4 yields the value 1 (rather than 1.75 or 2). The result is not an lvalue. The usual arithmetic conversions on the operands are performed.
Remainder operator %
The % (remainder) operator yields the remainder from the division of the left operand by the right operand. For example, the expression 5 % 3 yields 2. The result is not an lvalue. Both operands must have an integral or enumeration type. If the right operand evaluates to 0, the result is undefined. If either operand has a negative value, the result is such that the following expression always yields the value of a if b is not 0 and a/b is representable:
( a / b ) * b + a %b;
Addition operator +
The + (addition) operator yields the sum of its operands. Both operands must have an arithmetic type, or one operand must be a pointer to an object type and the other operand must have an integral or enumeration type. When both operands have an arithmetic type, the usual arithmetic conversions on the operands are performed. The result has the type produced by the conversions on the operands and is not an lvalue. A pointer to an object in an array can be added to a value having integral type. The result is a pointer of the same type as the pointer operand. The result refers to another element in the array, offset from the original element by the amount of the integral value treated as a subscript. If the resulting pointer points to storage outside the array, other than the first location outside the array, the result is undefined. A pointer to one element past the end of an array cannot be used to access the memory content at that address. The compiler does not provide boundary checking on the pointers. For example, after the addition, ptr points to the third element of the array:
int array[5]; int *ptr; ptr = array + 2;
114
XL C Language Reference
Subtraction operator
The - (subtraction) operator yields the difference of its operands. Both operands must have an arithmetic or enumeration type, or the left operand must have a pointer type and the right operand must have the same pointer type or an integral or enumeration type. You cannot subtract a pointer from an integral value. When both operands have an arithmetic type, the usual arithmetic conversions on the operands are performed. The result has the type produced by the conversions on the operands and is not an lvalue. When the left operand is a pointer and the right operand has an integral type, the compiler converts the value of the right to an address offset. The result is a pointer of the same type as the pointer operand. If both operands are pointers to elements in the same array, the result is the number of objects separating the two addresses. The number is of type ptrdiff_t, which is defined in the header file stddef.h. Behavior is undefined if the pointers do not refer to objects in the same array. Related information v Pointer arithmetic on page 68 v Pointer conversions on page 92
Each operand must have an integral or enumeration type. The compiler performs integral promotions on the operands, and then the right operand is converted to type int. The result has the same type as the left operand (after the arithmetic conversions). The right operand should not have a negative value or a value that is greater than or equal to the width in bits of the expression being shifted. The result of bitwise shifts on such values is unpredictable. If the right operand has the value 0, the result is the value of the left operand (after the usual arithmetic conversions). The << operator fills vacated bits with zeros. For example, if left_op has the value 4019, the bit pattern (in 16-bit format) of left_op is:
Chapter 6. Expressions and Operators
115
0000111110110011
Both operands must have arithmetic or enumeration types or be pointers to the same type. The type of the result is int and has the values 1 if the specified relationship is true, and 0 if false. The result is not an lvalue. If the operands have arithmetic types, the usual arithmetic conversions on the operands are performed. When the operands are pointers, the result is determined by the locations of the objects to which the pointers refer. If the pointers do not refer to objects in the same array, the result is not defined. A pointer can be compared to a constant expression that evaluates to 0. You can also compare a pointer to a pointer of type void*. The pointer is converted to a pointer of type void*. If two pointers refer to the same object, they are considered equal. If two pointers refer to nonstatic members of the same object, the pointer to the object declared later is greater, provided that they are not separated by an access specifier; otherwise the comparison is undefined. If two pointers refer to data members of the same union, they have the same address value. If two pointers refer to elements of the same array, or to the first element beyond the last element of an array, the pointer to the element with the higher subscript value is greater. You can only compare members of the same object with relational operators.
116
XL C Language Reference
is interpreted as:
(a < b) <= c
If the value of a is less than the value of b, the first relationship yields 1. The compiler then compares the value true (or 1) with the value of c (integral promotions are carried out if needed).
Both operands must have arithmetic or enumeration types or be pointers to the same type, or one operand must have a pointer type and the other operand must be a pointer to void or a null pointer. The type of the result is int and has the values 1 if the specified relationship is true, and 0 if false. If the operands have arithmetic types, the usual arithmetic conversions on the operands are performed. If the operands are pointers, the result is determined by the locations of the objects to which the pointers refer. If one operand is a pointer and the other operand is an integer having the value 0, the == expression is true only if the pointer operand evaluates to NULL. The != operator evaluates to true if the pointer operand does not evaluate to NULL. You can also use the equality operators to compare pointers to members that are of the same type but do not belong to the same object. The following expressions contain examples of equality and relational operators:
time < max_time == status < complete letter != EOF
Note: The equality operator (==) should not be confused with the assignment (=) operator. For example,
117
if (x == 3) evaluates to true (or 1) if x is equal to three. Equality tests like this should be coded with spaces between the operator and the operands to prevent unintentional assignments. while if (x = 3) is taken to be true because (x = 3) evaluates to a nonzero value (3). The expression also assigns the value 3 to x. Related information v Simple assignment operator = on page 123
Note: The bitwise AND (&) should not be confused with the logical AND. (&&) operator. For example, 1 & 4 evaluates to 0 while 1 && 4 evaluates to true
118
XL C Language Reference
The following example shows the values of a, b, and the result of a ^ b represented as 16-bit binary numbers:
bit pattern of a bit pattern of b bit pattern of a ^ b 0000000001011100 0000000000101110 0000000001110010
Note: The bitwise OR (|) should not be confused with the logical OR (||) operator. For example, 1 | 4 evaluates to 5 while 1 || 4 evaluates to true Related information v Trigraph sequences on page 26
119
Unlike the & (bitwise AND) operator, the && operator guarantees left-to-right evaluation of the operands. If the left operand evaluates to 0 (or false), the right operand is not evaluated. The following examples show how the expressions that contain the logical AND operator are evaluated:
Expression 1 && 0 1 && 4 0 && 0 Result false or 0 true or 1 false or 0
The following example uses the logical AND operator to avoid division by zero:
(y != 0) && (x / y)
The expression x / y is not evaluated when y != 0 evaluates to 0 (or false). Note: The logical AND (&&) should not be confused with the bitwise AND (&) operator. For example: 1 && 4 evaluates to 1 (or while 1 & 4 evaluates to 0 true)
Logical OR operator ||
The || (logical OR) operator indicates whether either operand is true. If either of the operands has a nonzero value, the result has the value 1. Otherwise, the result has the value 0. The type of the result is int. Both operands must have a arithmetic or pointer type. The usual arithmetic conversions on each operand are performed. Unlike the | (bitwise inclusive OR) operator, the || operator guarantees left-to-right evaluation of the operands. If the left operand has a nonzero (or true) value, the right operand is not evaluated. The following examples show how expressions that contain the logical OR operator are evaluated:
Expression 1 || 0 1 || 4 0 || 0 Result true or 1 true or 1 false or 0
The expression ++y is not evaluated when the expression ++x evaluates to a nonzero (or true) quantity.
120
XL C Language Reference
Note: The logical OR (||) should not be confused with the bitwise OR (|) operator. For example: 1 || 4 evaluates to 1 (or while 1 | 4 evaluates to 5 true)
Conditional expressions
A conditional expression is a compound expression that contains a condition (operand1), an expression to be evaluated if the condition evaluates to true (operand2), and an expression to be evaluated if the condition has the value false (operand3). The conditional expression contains one two-part operator. The ? symbol follows the condition, and the : symbol appears between the two action expressions. All expressions that occur between the ? and : are treated as one expression. The first operand must have a scalar type. The type of the second and third operands must be one of the following: v An arithmetic type v A compatible pointer, structure, or union type v void The second and third operands can also be a pointer or a null pointer constant. Two objects are compatible when they have the same type but not necessarily the same type qualifiers (volatile or const). Pointer objects are compatible if they have the same type or are pointers to void. The first operand is evaluated, and its value determines whether the second or third operand is evaluated: v If the value is true, the second operand is evaluated. v If the value is false, the third operand is evaluated. The result is the value of the second or third operand. If the second and third expressions evaluate to arithmetic types, the usual arithmetic conversions are performed on the values. The types of the second and third operands determine the type of the result as shown in the following tables. Conditional expressions have right-to-left associativity with respect to their first and third operands. The leftmost operand is evaluated first, and then only one of the remaining two operands is evaluated. The following expressions are equivalent:
a ? b : c ? d : e ? f : g a ? b : (c ? d : (e ? f : g))
121
Table 18. Types of operands and results in conditional C expressions (continued) Type of one operand Structure or union type Type of other operand Compatible structure or union type void Pointer to compatible type Type of result Structure or union type with all the qualifiers on both operands void Pointer to type with all the qualifiers specified for the type
NULL pointer (the constant 0) Pointer to type Pointer to void Pointer to void with all the qualifiers specified for the type
IBM extension In GNU C, a conditional expression is a valid lvalue, provided that its type is not void and both of its branches are valid lvalues. The following conditional expression (a ? b : c) is legal under GNU C:
(a ? b : c) = 5 /* Under GNU C, equivalent to (a ? b = 5 : (c = 5)) */
This extension is available when compiling in one of the extended language levels. End of IBM extension
The following expression calls the function printf, which receives the value of the variable c, if c evaluates to a digit. Otherwise, printf receives the character constant x.
printf(" c = %c\n", isdigit(c) ? c : x);
If the last operand of a conditional expression contains an assignment operator, use parentheses to ensure the expression evaluates properly. For example, the = operator has higher precedence than the ?: operator in the following expression:
int i,j,k; (i == 7) ? j ++ : k = j;
The compiler will interpret this expression as if it were parenthesized this way:
int i,j,k; ((i == 7) ? j ++ : k) = j;
122
XL C Language Reference
That is, k is treated as the third operand, not the entire assignment expression k = j. To assign the value of j to k when i == 7 is false, enclose the last operand in parentheses:
int i,j,k; (i == 7) ? j ++ : (k = j);
Assignment expressions
An assignment expression stores a value in the object designated by the left operand. There are two types of assignment operators: v Simple assignment operator = v Compound assignment operators The left operand in all assignment expressions must be a modifiable lvalue. The type of the expression is the type of the left operand. The value of the expression is the value of the left operand after the assignment has completed. The result of an assignment expression is not an lvalue. All assignment operators have the same precedence and have right-to-left associativity. Related information v Lvalues and rvalues on page 95 v Pointers on page 68 v Type qualifiers on page 56
123
is equivalent to
a = a * (b + c)
and not
a = a * b + c
The following table lists the compound assignment operators and shows an expression using each operator:
Operator += -= *= /= %= <<= >>= &= ^= |= Example index += 2 *(pointer++) -= 1 bonus *= increase time /= hours allowance %= 1000 result <<= num form >>= 1 mask &= 2 test ^= pre_test flag |= ON Equivalent expression index = index + 2 *pointer = *(pointer++) - 1 bonus = bonus * increase time = time / hours allowance = allowance % 1000 result = result << num form = form >> 1 mask = mask & 2 test = test ^ pre_test flag = flag | ON
Although the equivalent expression column shows the left operands (from the example column) twice, it is in effect evaluated only once. IBM extension When GNU C language features have been enabled, compound expressions and conditional expressions are allowed as lvalues, provided that their operands are
124
XL C Language Reference
lvalues. The following compound assignment of the compound expression (a, b) is legal under GNU C, provided that expression b, or more generally, the last expression in the sequence, is an lvalue:
(a,b) += 5 /* Under GNU C, this is equivalent to a, (b += 5) */
Comma expressions
A comma expression contains two operands of any type separated by a comma and has left-to-right associativity. The left operand is fully evaluated, possibly producing side effects, and its value, if there is one, is discarded. The right operand is then evaluated. The type and value of the result of a comma expression are those of its right operand, after the usual unary conversions. The result of a comma expression is not an lvalue. Any number of expressions separated by commas can form a single expression because the comma operator is associative. The use of the comma operator guarantees that the subexpressions will be evaluated in left-to-right order, and the value of the last becomes the value of the entire expression. In the following example, if omega has the value 11, the expression increments delta and assigns the value 3 to alpha:
alpha = (delta++, omega % 4);
A sequence point occurs after the evaluation of the first operand. The value of delta is discarded. Similarly, in the following example, the value of the expression:
intensity++, shade * increment, rotate(direction);
In some contexts where the comma character is used, parentheses are required to avoid ambiguity. For example, the function
f(a, (t = 3, t + 2), c);
has only three arguments: the value of a, the value 5, and the value of c. Other contexts in which parentheses are required are in field-length expressions in structure and union declarator lists, enumeration value expressions in enumeration declarator lists, and initialization expressions in declarations and initializers. In the previous example, the comma is used to separate the argument expressions in a function invocation. In this context, its use does not guarantee the order of evaluation (left to right) of the function arguments. The primary use of the comma operator is to produce side effects in the following situations: v Calling a function v Entering or repeating an iteration loop v Testing a condition v Other situations where a side effect is required but the result of the expression is not immediately needed
Chapter 6. Expressions and Operators
125
The following table gives some examples of the uses of the comma operator.
Statement for (i=0; i<2; ++i, f() ); if ( f(), ++i, i>1 ) */ } { /* ... Effects A for statement in which i is incremented and f() is called at each iteration. An if statement in which function f() is called, variable i is incremented, and variable i is tested against a value. The first two expressions within this comma expression are evaluated before the expression i>1. Regardless of the results of the first two expressions, the third is evaluated and its result determines whether the if statement is processed. A function call to func() in which a is incremented, the resulting value is passed to a function f(), and the return value of f() is passed to func(). The function func() is passed only a single argument, because the comma expression is enclosed in parentheses within the function argument list.
Because the order of subexpression evaluation is not specified, you can explicitly force the grouping of operands with operators by using parentheses. In the expression
a + b * c / d
the * and / operations are performed before + because of precedence. b is multiplied by c before it is divided by d because of associativity. The following tables list the language operators in order of precedence and show the direction of associativity for each operator. Operators that have the same rank have the same precedence.
Table 19. Precedence and associativity of postfix operators Rank 1 1 Right associative? Operator function member selection member selection Usage object . member pointer -> member
126
XL C Language Reference
Table 19. Precedence and associativity of postfix operators (continued) Rank 1 1 1 1 1 Right associative? Operator function subscripting function call value construction postfix increment postfix decrement Usage pointer [ expr ] expr ( expr_list ) type ( expr_list ) lvalue ++ lvalue --
Table 20. Precedence and associativity of unary operators Rank 2 2 2 2 2 2 2 2 2 2 2 Right associative? yes yes yes yes yes yes yes yes yes yes yes Operator function size of object in bytes size of type in bytes prefix increment prefix decrement bitwise negation not unary minus unary plus address of indirection or dereference type conversion (cast) Usage sizeof expr sizeof ( type ) ++ lvalue -- lvalue ~ expr ! expr - expr + expr & lvalue * expr ( type ) expr
Table 21. Precedence and associativity of binary operators Rank 3 3 3 4 4 5 5 6 6 6 6 7 7 8 9 10 Right associative? Operator function multiplication division modulo (remainder) binary addition binary subtraction bitwise shift left bitwise shift right less than less than or equal to greater than greater than or equal to equal not equal bitwise AND bitwise exclusive OR bitwise inclusive OR Usage expr * expr expr / expr expr % expr expr + expr expr - expr expr << expr expr >> expr expr < expr expr <= expr expr > expr expr >= expr expr == expr expr != expr expr & expr expr ^ expr expr | expr
127
Table 21. Precedence and associativity of binary operators (continued) Rank 11 12 13 14 14 14 14 14 14 14 14 14 14 14 15 yes yes yes yes yes yes yes yes yes yes yes Right associative? Operator function logical AND logical inclusive OR conditional expression simple assignment multiply and assign divide and assign modulo and assign add and assign subtract and assign shift left and assign shift right and assign bitwise AND and assign bitwise exclusive OR and assign bitwise inclusive OR and assign comma (sequencing) Usage expr && expr expr || expr expr ? expr : expr lvalue = expr lvalue *= expr lvalue /= expr lvalue %= expr lvalue += expr lvalue -= expr lvalue <<= expr lvalue >>= expr lvalue &= expr lvalue ^= expr lvalue |= expr expr , expr
If parentheses did not appear in these expressions, the operands and operators would be grouped in the same manner as indicated by the parentheses. For example, the following expressions produce the same output.
total = (4+(5*3)); total = 4+5*3;
Because the order of grouping operands with operators that are both associative and commutative is not specified, the compiler can group the operands and operators in the expression:
total = price + prov_tax + city_tax;
The grouping of operands and operators does not affect the result unless one ordering causes an overflow and another does not. For example, if price = 32767, prov_tax = -42, and city_tax = 32767, and all three of these variables have been declared as integers, the third statement total = ((price + city_tax) + prov_tax) will cause an integer overflow and the rest will not.
128
XL C Language Reference
Because intermediate values are rounded, different groupings of floating-point operators may give different results. In certain expressions, the grouping of operands and operators can affect the result. For example, in the following expression, each function call might be modifying the same global variables.
a = b() + c() + d();
This expression can give different results depending on the order in which the functions are called. If the expression contains operators that are both associative and commutative and the order of grouping operands with operators can affect the result of the expression, separate the expression into several expressions. For example, the following expressions could replace the previous expression if the called functions do not produce any side effects that affect the variable a.
a = b(); a += c(); a += d();
The order of evaluation for function call arguments or for the operands of binary operators is not specified. Therefore, the following expressions are ambiguous:
z = (x * ++y) / func1(y); func2(++i, x[i]);
If y has the value of 1 before the first statement, it is not known whether or not the value of 1 or 2 is passed to func1(). In the second statement, if i has the value of 1 before the expression is evaluated, it is not known whether x[1] or x[2] is passed as the second argument to func2().
129
130
XL C Language Reference
Chapter 7. Statements
A statement, the smallest independent computational unit, specifies an action to be performed. In most cases, statements are executed in sequence. The following is a summary of the statements available in C: v Labeled statements v v v v v Expression statements Block statements Selection statements Iteration statements Jump statements
Related information v Chapter 3, Data objects and declarations, on page 31 v Function declarations on page 153
Labeled statements
There are three kinds of labels: identifier, case, and default. Labeled statement syntax
identifier : statement
The label consists of the identifier and the colon (:) character. A label name must be unique within the function in which it appears. Case and default label statements only appear in switch statements. These labels are accessible only within the closest enclosing switch statement. case statement syntax
case constant_expression : statement
131
In a statement expression, the declaration of a local label must appear immediately after the left parenthesis and left brace, and must precede any ordinary declarations and statements. The label is defined in the usual way, with a name and a colon, within the statements of the statement expression. End of IBM extension
Labels as values
IBM extension The address of a label defined in the current function or a containing function can be obtained and used as a value wherever a constant of type void* is valid. The address is the return value when the label is the operand of the unary operator &&. The ability to use the address of label as a value is an extension to C99, implemented to facilitate porting programs developed with GNU C. In the following example, the computed goto statements use the values of label1 and label2 to jump to those spots in the function.
int main() { void * ptr1, *ptr2; ... label1: ... ... label2: ... ... ptr1 = &&label1; ptr2 = &&label2; if (...) { goto *ptr1; } else {
132
XL C Language Reference
Related information v Label value operator && on page 110 v Computed goto statement on page 148 End of IBM extension
Expression statements
An expression statement contains an expression. The expression can be null. Expression statement syntax
; expression
An expression statement evaluates expression, then discards the value of the expression. An expression statement without an expression is a null statement. The following are examples of statements:
printf("Account Number: \n"); marks = dollars * exch_rate; (difference < 0) ? ++losses : ++gain; /* call to the printf */ /* assignment to marks /* conditional increment */ */
Block statements
A block statement, or compound statement, lets you group any number of data definitions, declarations, and statements into one statement. All definitions, declarations, and statements enclosed within a single set of braces are treated as a single statement. You can use a block wherever a single statement is allowed. Block statement syntax
A block defines a local scope. If a data object is usable within a block and its identifier is not redefined, all nested blocks can use that data object.
Example of blocks
The following program shows how the values of data objects change in nested blocks:
Chapter 7. Statements
133
/** ** This example shows how data objects change in nested blocks. **/ #include <stdio.h> int main(void) { int x = 1; int y = 3;
/* Initialize x to 1
*/
if (y > 0) { int x = 2; /* Initialize x to 2 printf("second x = %4d\n", x); } printf("first x = %4d\n", x); return(0); }
*/
Two variables named x are defined in main. The first definition of x retains storage while main is running. However, because the second definition of x occurs within a nested block, printf("second x = %4d\n", x); recognizes x as the variable defined on the previous line. Because printf("first x = %4d\n", x); is not part of the nested block, x is recognized as the first definition of x.
Statement expressions
IBM extension A compound statement is a sequence of statements enclosed by braces. In GNU C, a compound statement inside parentheses may appear as an expression in what is called a statement expression. Statement expression syntax
statement ;
} )
The value of a statement expression is the value of the last simple expression to appear in the entire construct. If the last statement is not an expression, then the construct is of type void and has no value. The statement expression can be combined with the typeof operator to create complex function-like macros in which each operand is evaluated only once. For example:
#define SWAP(a,b) ( {__typeof__(a) temp; temp=a; a=b; b=temp;} )
134
XL C Language Reference
Selection statements
Selection statements consist of the following types of statements: v The if statement v The switch statement
The if statement
An if statement is a selection statement that allows more than one possible flow of control. In C, an if statement lets you conditionally process a statement when the specified test expression evaluates to a nonzero value. The test expression must be of arithmetic or pointer type. You can optionally specify an else clause on the if statement. If the test expression evaluates to a zero value and an else clause exists, the statement associated with the else clause runs. If the test expression evaluates to 1, the statement following the expression runs and the else clause is ignored. if statement syntax
if ( expression ) statement else statement
When if statements are nested and else clauses are present, a given else is associated with the closest preceding if statement within the same block. A single statement following any selection statements (if, switch) is treated as a compound statement containing the original statement. As a result any variables declared on that statement will be out of scope after the if statement. For example:
if (x) int i;
is equivalent to:
if (x) { int i; }
Variable i is visible only within the if statement. The same rule applies to the else part of the if statement.
Examples of if statements
The following example causes grade to receive the value A if the value of score is greater than or equal to 90.
if (score >= 90) grade = A;
The following example displays Number is positive if the value of number is greater than or equal to 0. If the value of number is less than 0, it displays Number is negative.
if (number >= 0) printf("Number is positive\n"); else printf("Number is negative\n");
135
if (paygrade == 7) if (level >= 0 && level <= 8) salary *= 1.05; else salary *= 1.04; else salary *= 1.06; cout << "salary is " << salary << endl;
The following example shows a nested if statement that does not have an else clause. Because an else clause always associates with the closest if statement, braces might be needed to force a particular else clause to associate with the correct if statement. In this example, omitting the braces would cause the else clause to associate with the nested if statement.
if (kegs > 0) { if (furlongs > kegs) fxph = furlongs/kegs; } else fxph = 0;
The following example shows an if statement nested within an else clause. This example tests multiple conditions. The tests are made in order of their appearance. If one test evaluates to a nonzero value, a statement runs and the entire if statement ends.
if (value > 0) ++increase; else if (value == 0) ++break_even; else ++decrease;
The switch body is enclosed in braces and can contain definitions, declarations, case clauses, and a default clause. Each case clause and default clause can contain statements.
136
XL C Language Reference
} default_clause case_clause
Note: An initializer within a type_definition, file_scope_data_declaration or block_scope_data_declaration is ignored. A case clause contains a case label followed by any number of statements. A case clause has the form: Case clause syntax
case_label
statement
A case label contains the word case followed by an integral constant expression and a colon. The value of each integral constant expression must represent a different value; you cannot have duplicate case labels. Anywhere you can put one case label, you can put multiple case labels. A case label has the form: case label syntax
case integral_constant_expression :
A default clause contains a default label followed by one or more statements. You can put a case label on either side of the default label. A switch statement can have only one default label. A default_clause has the form: Default clause statement
statement
The switch statement passes control to the statement following one of the labels or to the statement following the switch body. The value of the expression that precedes the switch body determines which statement receives control. This expression is called the switch expression. The value of the switch expression is compared with the value of the expression in each case label. If a matching value is found, control is passed to the statement following the case label that contains the matching value. If there is no matching
Chapter 7. Statements
137
value but there is a default label in the switch body, control passes to the default labelled statement. If no matching value is found, and there is no default label anywhere in the switch body, no part of the switch body is processed. When control passes to a statement in the switch body, control only leaves the switch body when a break statement is encountered or the last statement in the switch body is processed. If necessary, an integral promotion is performed on the controlling expression, and all expressions in the case statements are converted to the same type as the controlling expression. The switch expression can also be of class type if there is a single conversion to integral or enumeration type. Compiling with option -qinfo=gen finds case labels that fall through when they should not.
138
XL C Language Reference
If the switch expression matches a case expression, the statements following the case expression are processed until a break statement is encountered or the end of the switch body is reached. In the following example, break statements are not present. If the value of text[i] is equal to A, all three counters are incremented. If the value of text[i] is equal to a, lettera and total are increased. Only total is increased if text[i] is not equal to A or a.
char text[100]; int capa, lettera, total; // ... for (i=0; i<sizeof(text); i++) { switch (text[i]) { case A: capa++; case a: lettera++; default: total++; } }
The following switch statement performs the same statements for more than one case label:
/** ** This example contains a switch statement that performs ** the same statement for more than one case label. **/ #include <stdio.h> int main(void) { int month; /* Read in a month value */ printf("Enter month: "); scanf("%d", &month); /* Tell what season it falls into */ switch (month) { case 12: case 1: case 2: printf("month %d is a winter month\n", month); break; case 3: case 4: case 5: printf("month %d is a spring month\n", month); break; case 6: case 7: case 8:
Chapter 7. Statements
139
printf("month %d is a summer month\n", month); break; case 9: case 10: case 11: printf("month %d is a fall month\n", month); break; case 66: case 99: default: printf("month %d is not a valid month\n", month); } return(0); }
If the expression month has the value 3, control passes to the statement:
printf("month %d is a spring month\n", month);
The break statement passes control to the statement following the switch body. Related information v -qinfo=gen in the XL C Compiler Reference v Case and Default Labels on page 131 v The break statement on page 144
Iteration statements
Iteration statements consist of the following types of statements: v The while statement v The do statement v The for statement v Related information v Boolean types on page 40
The expression must be of arithmetic or pointer type. The expression is evaluated to determine whether or not to process the body of the loop. If the expression evaluates to 0, the body of the loop never runs. If the expression does not evaluate to 0, the loop body is processed. After the body has run, control passes back to the expression. Further processing depends on the value of the condition.
140
XL C Language Reference
A break, return, or goto statement can cause a while statement to end, even when the condition does not evaluate to 0. In the following example, item[index] triples and is printed out, as long as the value of the expression ++index is less than MAX_INDEX. When ++index evaluates to MAX_INDEX, the while statement ends.
/** ** This example illustrates the while statement. **/ #define MAX_INDEX (sizeof(item) / sizeof(item[0])) #include <stdio.h> int main(void) { static int item[ ] = { 12, 55, 62, 85, 102 }; int index = 0; while (index < MAX_INDEX) { item[index] *= 3; printf("item[%d] = %d\n", index, item[index]); ++index; } return(0); }
The do statement
A do statement repeatedly runs a statement until the test expression evaluates to 0. Because of the order of processing, the statement is run at least once. do statement syntax
do statement while ( expression ) ;
The expression must be of arithmetic or pointer type. The body of the loop is run before the controlling while clause is evaluated. Further processing of the do statement depends on the value of the while clause. If the while clause does not evaluate to 0, the statement runs again. When the while clause evaluates to 0, the statement ends. A break, return, or goto statement can cause the processing of a do statement to end, even when the while clause does not evaluate to 0. The following example keeps incrementing i while i is less than 5:
#include <stdio.h> int main(void) { int i = 0; do { i++; printf("Value of i: %d\n", i); } while (i < 5); return 0; }
Chapter 7. Statements
141
expression1 is the initialization expression. It is evaluated only before the statement is processed for the first time. You can use this expression to initialize a variable. You can also use this expression to declare a variable, provided that the variable is not declared as static (it must be automatic and may also be declared as register). If you declare a variable in this expression, or anywhere else in statement, that variable goes out of scope at the end of the for loop. If you do not want to evaluate an expression prior to the first iteration of the statement, you can omit this expression. expression2 is the conditional expression. It is evaluated before each iteration of the statement. expression2 must be of arithmetic or pointer type. If it evaluates to 0, the statement is not processed and control moves to the next statement following the for statement. If expression2 does not evaluate to 0, the statement is processed. If you omit expression2, it is as if the expression had been replaced by 1, and the for statement is not terminated by failure of this condition. expression3 is evaluated after each iteration of the statement. This expression is often used for incrementing, decrementing, or assigning to a variable. This expression is optional. A break, return, or goto statement can cause a for statement to end, even when the second expression does not evaluate to 0. If you omit expression2, you must use a break, return, or goto statement to end the for statement.
142
XL C Language Reference
The following sequence of statements accomplishes the same task. Note the use of the while statement instead of the for statement.
int count = 1; while (count <= 20) { printf("count = %d\n", count); count++; }
The following for statement will continue running until scanf receives the letter e:
for (;;) { scanf("%c", &letter); if (letter == \n) continue; if (letter == e) break; printf("You entered the letter %c\n", letter); }
The following for statement contains multiple initializations and increments. The comma operator makes this construction possible. The first comma in the for expression is a punctuator for a declaration. It declares and initializes two integers, i and j. The second comma, a comma operator, allows both i and j to be incremented at each step through the loop.
for (int i = 0, j = 50; i < 10; ++i, j += 50) { cout << "i = " << i << "and j = " << j << endl; }
The following example shows a nested for statement. It prints the values of an array having the dimensions [5][3].
for (row = 0; row < 5; row++) for (column = 0; column < 3; column++) printf("%d\n", table[row][column]);
The outer statement is processed as long as the value of row is less than 5. Each time the outer for statement is executed, the inner for statement sets the initial value of column to zero and the statement of the inner for statement is executed 3 times. The inner statement is executed as long as the value of column is less than 3.
Jump statements
Jump statements consist of the following types of statements: v The break statement v The continue statement v The return statement
Chapter 7. Statements
143
In an iterative statement, the break statement ends the loop and moves control to the next statement outside the loop. Within nested statements, the break statement ends only the smallest enclosing do, for, switch, or while statement. In a switch statement, the break passes control out of the switch body to the next statement outside the switch statement.
A continue statement can only appear within the body of an iterative statement, such as do, for, or while. The continue statement ends the processing of the action part of an iterative statement and moves control to the loop continuation portion of the statement. For example, if the iterative statement is a for statement, control moves to the third expression in the condition part of the statement, then to the second expression (the test) in the condition part of the statement. Within nested statements, the continue statement ends only the current iteration of the do, for, or while statement immediately enclosing it.
144
XL C Language Reference
for (i = 0; i < SIZE; i++) { if (rates[i] <= 1.00) /* skip rates <= 1.00 continue; printf("rate = %.2f\n", rates[i]); } return(0); }
*/
The following example shows a continue statement in a nested loop. When the inner loop encounters a number in the array strings, that iteration of the loop ends. Processing continues with the third expression of the inner loop. The inner loop ends when the \0 escape sequence is encountered.
/** ** This program counts the characters in strings that are part ** of an array of pointers to characters. The count excludes ** the digits 0 through 9. **/ #include <stdio.h> #define SIZE 3 int main(void) { static char *strings[SIZE] = { "ab", "c5d", "e5" }; int i; int letter_count = 0; char *pointer; for (i = 0; i < SIZE; i++) /* for each string */ /* for each each character */ for (pointer = strings[i]; *pointer != \0; ++pointer) { /* if a number */ if (*pointer >= 0 && *pointer <= 9) continue; letter_count++; } printf("letter count = %d\n", letter_count); return(0); }
Chapter 7. Statements
145
A value-returning function should include a return statement, containing an C expression. If an expression is not given on a return statement in a function declared with a non-void return type, the compiler issues a warning message. If the data type of the expression is different from the function return type, conversion of the return value takes place as if the value of the expression were assigned to an object with the same function return type. For a function of return type void, a return statement is not strictly necessary. If the end of such a function is reached without encountering a return statement, control is passed to the caller as if a return statement without an expression were encountered. In other words, an implicit return takes place upon completion of the final statement, and control automatically returns to the calling function.
The following function searches through an array of integers to determine if a match exists for the variable number. If a match exists, the function match returns the value of i. If a match does not exist, the function match returns the value -1 (negative one).
int match(int number, int array[ ], int n) { int i; for (i = 0; i < n; i++) if (number == array[i]) return (i); return(-1); }
for (int i = 0; i < c; ++i;) /* do the copying */ b[i] = a[1]; /* implicit return */ }
In this example, the return statement is used to cause a premature termination of the function, similar to a break statement.
146
XL C Language Reference
An expression appearing in a return statement is converted to the return type of the function in which the statement appears. If no implicit conversion is possible, the return statement is invalid. Related information v Function return type specifiers on page 159 v Function return values on page 159
Because the goto statement can interfere with the normal sequence of processing, it makes a program more difficult to read and maintain. Often, a break statement, a continue statement, or a function call can eliminate the need for a goto statement. If an active block is exited using a goto statement, any local variables are destroyed when control is transferred from that block. You cannot use a goto statement to jump over initializations. A goto statement is allowed to jump within the scope of a variable length array, but not past any declarations of objects with variably modified types. The following example shows a goto statement that is used to jump out of a nested loop. This function could be written without using a goto statement.
/** ** This example shows a goto statement that is used to ** jump out of a nested loop. **/ #include <stdio.h> void display(int matrix[3][3]); int main(void) { int matrix[3][3]= display(matrix); return(0); }
{1,2,3,4,5,2,8,9,10};
void display(int matrix[3][3]) { int i, j; for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) { if ( (matrix[i][j] < 1) || (matrix[i][j] > 6) ) goto out_of_bounds; printf("matrix[%d][%d] = %d\n", i, j, matrix[i][j]); } return; out_of_bounds: printf("number must be 1 through 6\n"); }
Chapter 7. Statements
147
The *expression is an expression of type void*. Related information v Labels as values on page 132 v Label value operator && on page 110 End of IBM extension
Null statement
The null statement performs no operation. It has the form:
;
A null statement can hold the label of a labeled statement or complete the syntax of an iterative statement. The following example initializes the elements of the array price. Because the initializations occur within the for expressions, a statement is only needed to finish the for syntax; no operations are required.
for (i = 0; i < 3; price[i++] = 0) ;
A null statement can be used when a label is needed before the end of a block statement. For example:
void func(void) { if (error_detected) goto depart; /* further processing */ depart: ; /* null statement required */ }
148
XL C Language Reference
input:
, constraint ( C_expression )
output:
, constraint ( C_expression )
The qualifier volatile instructs the compiler that the assembler instructions may update memory not listed in output, input, or clobbers. The code_format_string is the source text of the asm instructions and is a string literal similar to a printf format specifier. The string consists of a comma-separated list of % specifiers, each of which corresponds to an input or output operand. The % specifier can take either of the following forms: v %digit, where digit can be 0 to 9, and refers to the sequential number of the input or output operand. v %[symbolic_name], where the symbolic_name can be referenced within the assembler code. The input is a comma-separated list of input operands. The output is a comma-separated list of output operands.
Chapter 7. Statements
149
If pointer expressions are used in input or output, the assembly instructions should honor the ANSI aliasing rule (see Type-based aliasing on page 69 for more information). This means that indirect addressing using values in pointer expression operands should be consistent with the pointer types; otherwise, you must disable the -qalias=ansi option during compilation. clobbers is a comma-separated list of register names enclosed in double quotes. These are registers that can be updated by the asm instruction. The constraint is a string literal specifying the constraints for the operand, one character per constraint. The C_expression is a C expression whose value is used as the operand for the asm instruction. Output operands must be modifiable lvalues. The following constraints are supported: = Write-only operand. + Read and write operand. & An operand may be modified before the instruction is finished using the input operands; a register that is used as input should not be reused here. b Use a general register other than zero. f Use a floating-point register.
m A memory operand supported by the machine. n Handle in the same way as i. o Handle in the same way as m. r Use a general register.
v Use a vector register. 0, 1, 2, ...66 A matching constraint. Allocate the same register in output as in the corresponding input. I, J, K, M, N, O, P, G, S, T Constant values. Fold the expression in the operand and substitute the value into the % specifier. Related information v -qalias=ansi in the XL C Compiler Reference
150
XL C Language Reference
add is the op code of the instruction, understood by the assembler. %0, %1 and %2 are the operands, which are to be substituted by the C expressions in the output/input operand fields. The output operand uses the = constraint to indicate that a modifiable operand is required; and the r constraint to indicate that a general purpose register is required. Likewise, the r in the input operands indicates that general purpose registers are required. Within these restrictions, the compiler is free to choose any registers to substitute for %0, %1, and %2. The following example illustrates the use of the symbolic names for input and output operands:
int a ; int b = 1, c = 2, d = 3 ; __asm("addc %[result],%[first],%[second]" :[result]"=r"(a) :[first]"r"(b), [second]"r"(d) );
Chapter 7. Statements
151
152
XL C Language Reference
Chapter 8. Functions
In the context of programming languages, the term function means an assemblage of statements used for computing an output value. The word is used less strictly than in mathematics, where it means a set relating input variables uniquely to output variables. Functions in C programs may not produce consistent outputs for all inputs, may not produce output at all, or may have side effects. Functions can be understood as user-defined operations, in which the parameters of the parameter list, if any, are the operands. This section discusses the following topics: v Function declarations and definitions v Function storage class specifiers on page 156 v Function specifiers on page 157 v Function return type specifiers on page 159 v Function declarators on page 160 v Function attributes on page 162 v v v v The main() function on page 167 Function calls on page 168 Pointers to functions on page 169 Nested functions on page 170
do not allocate storage. The function definition contains a function declaration and the body of a function. The body is a block of statements that perform the work of the function. The identifiers declared in this example allocate storage; they are both declarations and definitions.
float square(float x) { return x*x; }
A function can be declared several times in a program, but all declarations for a given function must be compatible; that is, the return type is the same and the parameters have the same type. However, a function can only have one definition. Declarations are typically placed in header files, while definitions appear in source files.
Function declarations
A function identifier preceded by its return type and followed by its parameter list is called a function declaration or function prototype. The prototype informs the compiler of the format and existence of a function prior to its use. The compiler
Copyright IBM Corp. 1998, 2005
153
checks for mismatches between the parameters of a function call and those in the function declaration. The compiler also uses the declaration for argument type checking and argument conversions. If a function declaration is not visible at the point at which a call to the function is made, the compiler assumes an implicit declaration of extern int func(); However, for conformance to C99, you should explicitly prototype every function before making a call to it. The elements of a declaration for a function are as follows: v Function storage class specifiers, which specify linkage v Function return type specifiers, which specify the data type of a value to be returned v Function specifiers, which specify additional properties for functions v Function declarators, which include function identifiers as well as lists of parameters All function declarations have the form: Function declaration syntax
return_type_specifier storage_class_specifier function_specifier function_declarator ;
IBM In addition, for compatibility with GNU C, XL C allows you to use attributes to modify the properties of functions. They are described in Function attributes on page 162.
Function definitions
The elements of a function definition are as follows: v Function storage class specifiers, which specify linkage v Function return type specifiers, which specify the data type of a value to be returned v Function specifiers, which specify additional properties for functions v Function declarators, which include function identifiers as well as lists of parameters v The function body, which is a braces-enclosed series of statements representing the actions that the function performs In addition, for compatibility with GNU C, XL C allows you to use attributes to modify the properties of functions. They are described in Function attributes on page 162.
IBM
storage_class_specifier
function_specifier
154
XL C Language Reference
This fragment declares a pointer p1 to a function that takes a pointer to a constant character and returns an integer:
int (*p1) (const char*);
The following code fragment declares a function f1 that takes an integer argument, and returns a pointer to a function that takes an integer argument and returns an integer:
int (*f1(int)) (int);
Alternatively, a typedef can be used for the complicated return type of function f1:
typedef int f1_return_type(int); f1_return_type* f1(int);
The following declaration is of an external function f2 that takes a constant integer as its first argument, can have a variable number and variable types of other arguments, and returns type int.
int extern f2(const int, ...);
Function f6 is a const class member function of class X, takes no arguments, and has a return type of int:
class X { public: int f6() const; };
The function sum has external linkage, returns an object that has type int, and has two parameters of type int declared as x and y. The function body contains a single statement that returns the sum of x and y. The following function set_date declares a pointer to a structure of type date as a parameter. date_ptr has the storage class specifier register.
void set_date(register struct date *date_ptr) { date_ptr->mon = 12; date_ptr->day = 25; date_ptr->year = 87; }
Chapter 8. Functions
155
Compatible functions
For two functions, the composite type must meet the following requirements: v If one of the function types has a parameter type list, the composite type is a function prototype with the same parameter type list. v If both types are function types with parameter lists, then each parameter in the parameter list of the composite is the composite type of the corresponding parameters. If the function declarator is not part of the function declaration, the parameters may have incomplete type. The parameters may also specify variable length array types by using the [*] notation in their sequences of declarator specifiers. The following are examples of compatible function prototype declarators:
double double double double maximum(int maximum(int maximum(int maximum(int n, n, n, n, int int int int m, m, m, m, double double double double a[n][m]); a[*][*]); a[ ][*]); a[ ][m]);
156
XL C Language Reference
Function specifiers
The only available function specifier for functions declarations and definitions is inline, described below.
The use of the inline specifier does not change the meaning of the function. However, the inline expansion of a function may not preserve the order of evaluation of the actual arguments. The most efficient way to code an inline function is to place the inline function definition in a header file, and then include the header in any file containing a call to the function which you would like to inline. Note: The inline qualifier is represented by the following keywords: v The inline keyword is only recognized under compilation with c99 or with the -qlanglvl=stdc99 or -qlanglvl=extc99 options (or equivalent pragmas) or -qkeyword=inline. Note that the latter option is enabled by default for xlc in the configuration file that is shipped with the compiler. The __inline__ keyword is recognized at all language levels; however, see Linkage of inline functions below for the semantics of this keyword. Related information v The always_inline function attribute on page 163 v The noinline function attribute on page 165 v -qlanglvl and -qkeyword in the XL C Compiler Reference
Chapter 8. Functions
157
void g() { printf("foo called from g: return value = %d, address = %p\n", foo(), &foo); } // b.c #include <stdio.h> inline int foo(){ return 3; } void g(); int main() { printf("foo called from main: return value = %d, address = %p\n", foo(), &foo); g(); }
Since inline functions are treated as having internal linkage, an inline function definition can co-exist with a regular, external definition of a function with the same name in another translation unit. However, when you call the function from the file containing the inline definition, the compiler may choose either the inline version defined in the same file or the external version defined in another file for the call; your program should not rely on the inline version being called. In the following example, the call to foo from function g could return either 6 or 3:
// a.c #include <stdio.h> inline int foo(){ return 6; } void g() { printf("foo called from g: return value = %d\n", foo()); } // b.c #include <stdio.h> int foo(){ return 3; } void g(); int main() { printf("foo called from main: return value = %d\n", foo()); g(); }
Similarly, if you define a function as extern inline, or redeclare an inline function as extern, the function simply becomes a regular, external function and is not inlined.
158
XL C Language Reference
IBM If you specify the __inline__ keyword, with the trailing underscores, the compiler uses the GNU C semantics for inline functions. In contrast to the C99 semantics, a function defined as __inline__ provides an external definition only; a function defined as static __inline__ provides an inline definition with internal linkage (as in C99); and a function defined as extern __inline__, when compiled with optimization enabled, allows the co-existence of an inline and external definition of the same function. For more information on the GNU C implementation of inline functions, see the GCC documentation, available at http://gcc.gnu.org/onlinedocs/.
The user-defined type may also be defined within the function declaration.
enum count{one, two, three} counter(); // legal
Chapter 8. Functions
159
The function add() can be called as shown in the following code fragment:
int a = 10, b = 20; int answer = add(a, b); // answer is 30
In this example, the return statement initializes a variable of the returned type. The variable answer is initialized with the int value 30. The type of the returned expression is checked against the returned type. All standard and user-defined conversions are performed as necessary. Each time a function is called, new copies of its variables with automatic storage are created. Because the storage for these automatic variables may be reused after the function has terminated, a pointer to an automatic variable should not be returned. Related information v The return statement on page 145 v The auto storage class specifier on page 35
Function declarators
Function declarators consist of the following elements: v An identifier, or name v Parameter declarations, which specify the parameters that can be passed to the function in a function call Function declarator syntax
identifier ( parameter_declaration )
Parameter declarations
The function declarator includes the list of parameters that can be passed to the function when it is called by another function, or by itself. Function parameter declaration syntax
, ( parameter , ... )
parameter
type_specifier register declarator
An empty argument list in a function definition indicates that a function that takes no arguments. An empty argument list in a function declaration indicates that a function may take any number or type of arguments. Thus,
160
XL C Language Reference
simply indicates that the number and type of parameters is not known. To explicitly indicate that a function does not take any arguments, you should define the function with the keyword void. An ellipsis at the end of the parameter specifications is used to specify that a function has a variable number of parameters. The number of parameters is equal to, or greater than, the number of parameter specifications.
int f(int, ...);
At least one parameter declaration, as well as a comma before the ellipsis, are both required in C. Related information v The void type on page 42 v Type specifiers on page 39 v Type qualifiers on page 56
Parameter types
In a function declaration, or prototype, the type of each parameter must be specified. In the function definition, if the type of a parameter is not specified, it is assumed to be int. A variable of a user-defined type may be declared in a parameter declaration, as in the following example, in which x is declared for the first time:
struct X { int i; }; void print(struct X x);
The user-defined type can also be defined within the parameter declaration.
void print(struct X { int i; } x); // legal
Parameter names
In a function definition, each parameter must have an identifier. In a function declaration, or prototype, specifying an identifier is optional. Thus, the following example is legal in a function declaration:
int func(int,long);
161
optimizations. This particular usage of the static keyword is highly prescribed. The keyword may only appear in the outermost array type derivation and only in function parameter declarations. If the caller of the function does not abide by these restrictions, the behavior is undefined. The following examples show how the feature can be used.
void foo(int arr [static 10]); void foo(int arr void foo(int arr void foo(int arr void foo(int arr /* arr points to the first of at least 10 ints [const 10]); /* arr is a const pointer [static const i]); /* arr points to at least i ints; i is computed at run time. [const static i]); /* alternate syntax to previous example [const]); /* const pointer to int */ */ */ */ */
Related information v The static storage class specifier on page 36 v Arrays on page 70 v Array subscripting operator [ ] on page 100
Function attributes
IBM extension Function attributes are extensions implemented to enhance the portability of programs developed with GNU C. Specifiable attributes for functions provide explicit ways to help the compiler optimize function calls and to instruct it to check more aspects of the code. Others provide additional functionality. IBM C implements a subset of the GNU C function attributes. If a particular function attribute is not implemented, its specification is accepted and the semantics are ignored. These language features are collectively available when compiling in any of the extended language levels. A function attribute is specified with the keyword __attribute__ followed by the attribute name and any additional arguments the attribute name requires. A function __attribute__ specification is included in the declaration or definition of a function. The syntax takes the following forms: Function attribute syntax: function declaration
function declarator __attribute__
, (( attribute_name __ attribute_name __ )) ;
162
XL C Language Reference
{ function body }
The function attribute in a function declaration is always placed after the declarator, including the parenthesized parameter declaration:
/* Specify the attribute on a function prototype declaration */ void f(int i, int j) __attribute__((individual_attribute_name)); void f(int i, int j) { }
Due to ambiguities in parsing old-style parameter declarations, a function definition must have the attribute specification precede the declarator:
int __attribute__((individual_attribute_name)) foo(int i) { }
A function attribute specification using the form __attribute_name__ (that is, the attribute name with double underscore characters leading and trailing) reduces the likelihood of a name conflict with a macro of the same name. Related information v Variable attributes on page 83
The aliased function can be defined after the specification of its alias with this function attribute. C also allows an alias specification in the absence of a definition of the aliased function in the same compilation unit. The following declares bar to be an alias for __foo:
void __foo(){ /* function body */ } void bar() __attribute__((alias("__foo")));
The compiler does not check for consistency between the declaration of bar and definition of __foo. Such consistency remains the responsibility of the programmer.
Chapter 8. Functions
163
Related information v The inline function specifier on page 157 v The noinline function attribute on page 165
The following kinds of functions should not be declared const: v A function with pointer arguments which examines the data pointed to. v A function that calls a non-const function. Related information v #pragma isolated_call in the XL C Compiler Reference
where string_index Is a constant integral expression that specifies which argument in the declaration of the user function is the format string argument. first_to_check Is a constant integral expression that specifies the first argument to check against the format string. If there are no arguments to check against the format string (that is, diagnostics should only be performed on the format
164
XL C Language Reference
string syntax and semantics), first_to_check should have a value of 0. For strftime-style formats, first_to_check is required to be 0. It is possible to specify multiple format attributes on the same function, in which case, all apply.
void my_fn(const char* a, const char* b, ...) __attribute__((__format__(__printf__,1,0), __format__(__scanf__,2,3)));
It is also possible to diagnose the same string for different format styles. All styles are diagnosed.
void my_fn(const char* a, const char* b, ...) __attribute__((__format__(__printf__,2,3), __format__(__strftime__,2,0), __format__(__scanf__,2,3)));
where string_index is a constant integral expression that specifies which argument is the format string argument, starting from 1. It is possible to specify multiple format_arg attributes on the same function, in which case, all apply.
extern char* my_dgettext(const char* my_format, const char* my_format2) __attribute__((__format_arg__(1))) __attribute__((__format_arg__(2))); printf(my_dgettext("%","%")); //printf-style format diagnostics are performed on both "%" strings
Other than preventing inlining, the attribute does not remove the semantics of inline functions.
Chapter 8. Functions
165
Registers saved by the calling function may not necessarily be restored before calling the nonreturning function. Related information v #pragma leaves in the XL C Compiler Reference
Related information v The alias function attribute on page 163 v #pragma weakin the XL C Compiler Reference v The weak variable attribute on page 86
166
XL C Language Reference
Although any name can be given to these parameters, they are usually referred to as argc and argv. The first parameter, argc (argument count) is an integer that indicates how many arguments were entered on the command line when the program was started. The second parameter, argv (argument vector), is an array of pointers to arrays of character objects. The array objects are null-terminated strings, representing the arguments that were entered on the command line when the program was started. The first element of the array, argv[0], is a pointer to the character array that contains the program name or invocation name of the program that is being run from the command line. argv[1] indicates the first argument passed to the program, argv[2] the second argument, and so on. The following example program backward prints the arguments entered on a command line such that the last argument is printed first:
#include <stdio.h> int main(int argc, char *argv[]) { while (--argc > 0) printf(%s , argv[argc]); }
The arguments argc and argv would contain the following values:
Object argc argv[0] argv[1] Value 3 pointer to string backward pointer to string string1
Chapter 8. Functions
167
Related information v The extern storage class specifier on page 37 v The inline function specifier on page 157 v The static storage class specifier on page 36 v Function calls
Function calls
Once a function has been declared and defined, it can be called from anywhere within the program: from within the main function, from another function, and even from itself. Calling the function involves specifying the function name, followed by the function call operator and any data values the function expects to receive. These values are the arguments for the parameters defined for the function, and the process just described is called passing arguments to the function. Passing arguments can be done in two ways: v Pass by value, which copies the value of an argument to the corresponding parameter in the called function v Pass by reference, which passes the address of an argument to the corresponding parameter in the called function Related information v Function argument conversions on page 93 v Function call operator ( ) on page 99
Pass by value
When you use pass-by-value, the compiler copies the value of an argument in a calling function to a corresponding non-pointer parameter in the called function definition. The parameter in the called function is initialized with the value of the passed argument. As long as the parameter has not been declared as constant, the value of the parameter can be changed, but the changes are only performed within the scope of the called function only; they have no effect on the value of the argument in the calling function. In the following example, main passes func two values: 5 and 7. The function func receives copies of these values and accesses them by the identifiers a and b. The function func changes the value of a. When control passes back to main, the actual values of x and y are not changed.
/** ** This example illustrates calling a function by value **/ #include <stdio.h> void func (int a, int b) { a += b; printf("In func, a = %d }
b = %d\n", a, b);
168
XL C Language Reference
y = %d\n", x, y);
Pass by reference
Passing by by reference refers to a method of passing the address of an argument in the calling function to a corresponding parameter in the called function. In C, the corresponding parameter in the called function must be declared as a pointer type. In this way, the value of the argument in the calling function can be modified by the called function. The following example shows how arguments are passed by reference. Note that pointer parameters are initialized with pointer values when the function is called. When the function swapnum() is called, the actual values of the variables a and b are exchanged because they are passed by reference. The output is:
A is 20 and B is 10
Related information
Pointers to functions
A pointer to a function points to the address of the executable code of the function. You can use pointers to call functions and to pass functions as arguments to other functions. You cannot perform pointer arithmetic on pointers to functions. The type of a pointer to a function is based on both the return type and parameter types of the function. A declaration of a pointer to a function must have the pointer name in parentheses. The function call operator () has a higher precedence than the dereference operator *. Without them, the compiler interprets the statement as a function that returns a pointer to a specified return type. For example:
int *f(int a); /* function f returning an int* */ int (*g)(int a); /* pointer g to a function returning an int */ char (*h)(int, int) /* h is a function that takes two integer parameters and returns char */
In the first declaration, f is interpreted as a function that takes an int as argument, and returns a pointer to an int. In the second declaration, g is interpreted as a pointer to a function that takes an int argument and that returns an int. Related information v Pointers on page 68 v Pointer conversions on page 92 v The extern storage class specifier on page 156
Chapter 8. Functions
169
Nested functions
IBM extension A nested function is a function defined inside the definition of another function. It can be defined wherever a variable declaration is permitted, which allows nested functions within nested functions. Within the containing function, the nested function can be declared prior to being defined by using the auto keyword. Otherwise, a nested function has internal linkage. The language feature is an extension to C89 and C99, implemented to facilitate porting programs developed with GNU C. A nested function can access all identifiers of the containing function that precede its definition. A nested function must not be called after the containing function exits. A nested function cannot use a goto statement to jump to a label in the containing function, or to a local label declared with the __label__ keyword inherited from the containing function. Related information v Locally declared labels on page 132 End of IBM extension
170
XL C Language Reference
Preprocessor directives begin with the # token followed by a preprocessor keyword. The # token must appear as the first character that is not white space on a line. The # is not part of the directive name and can be separated from the name with white spaces. A preprocessor directive ends at the new-line character unless the last character of the line is the \ (backslash) character. If the \ character appears as the last character in the preprocessor line, the preprocessor interprets the \ and the new-line character as a continuation marker. The preprocessor deletes the \ (and the following new-line character) and splices the physical source lines into continuous logical lines. White space is allowed between backslash and the end of line character or the physical end of record. However, this white space is usually not visible during editing. Except for some #pragma directives, preprocessor directives can appear anywhere in a program.
171
The #define directive can contain: v Object-like macros v Function-like macros The following are some differences between #define and the const type qualifier: v The #define directive can be used to create a name for a numerical, character, or string constant, whereas a const object of any type can be declared. v A const object is subject to the scoping rules for variables, whereas a constant created using #define is not. v Unlike a const object, the value of a macro does not appear in the intermediate source code used by the compiler because they are expanded inline. The inline expansion makes the macro value unavailable to the debugger. v A macro can be used in a constant expression, such as an array bound, whereas a const object cannot. Related information v The const type qualifier on page 57
Object-like macros
An object-like macro definition replaces a single identifier with the specified replacement tokens. The following object-like definition causes the preprocessor to replace all subsequent instances of the identifier COUNT with the constant 1000 :
#define COUNT 1000
If the statement
int arry[COUNT];
appears after this definition and in the same file as the definition, the preprocessor would change the statement to
int arry[1000];
in the output of the preprocessor. Other definitions can make reference to the identifier COUNT:
#define MAX_COUNT COUNT + 100
The preprocessor replaces each subsequent occurrence of MAX_COUNT with COUNT + 100, which the preprocessor then replaces with 1000 + 100.
172
XL C Language Reference
If a number that is partially built by a macro expansion is produced, the preprocessor does not consider the result to be a single value. For example, the following will not result in the value 10.2 but in a syntax error.
#define a 10 a.2
Identifiers that are partially built from a macro expansion may not be produced. Therefore, the following example contains two identifiers and results in a syntax error:
#define d efg abcd
Function-like macros
More complex than object-like macros, a function-like macro definition declares the names of formal parameters within parentheses, separated by commas. An empty formal parameter list is legal: such a macro can be used to simulate a function that takes no arguments. C99 adds support for function-like macros with a variable number of arguments. Function-like macro definition: An identifier followed by a parameter list in parentheses and the replacement tokens. The parameters are imbedded in the replacement code. White space cannot separate the identifier (which is the name of the macro) and the left parenthesis of the parameter list. A comma must separate each parameter. For portability, you should not have more than 31 parameters for a macro. The parameter list may end with an ellipsis (...). In this case, the identifier __VA_ARGS__ may appear in the replacement list. Function-like macro invocation: An identifier followed by a comma-separated list of arguments in parentheses. The number of arguments should match the number of parameters in the macro definition, unless the parameter list in the definition ends with an ellipsis. In this latter case, the number of arguments in the invocation should exceed the number of parameters in the definition. The excess are called trailing arguments. Once the preprocessor identifies a function-like macro invocation, argument substitution takes place. A parameter in the replacement code is replaced by the corresponding argument. If trailing arguments are permitted by the macro definition, they are merged with the intervening commas to replace the identifier __VA_ARGS__, as if they were a single argument. Any macro invocations contained in the argument itself are completely replaced before the argument replaces its corresponding parameter in the replacement code. A macro argument can be empty (consisting of zero preprocessing tokens). For example,
#define SUM(a,b,c) a + b + c SUM(1,,3) /* No error message. 1 is substituted for a, 3 is substituted for c. */
If the identifier list does not end with an ellipsis, the number of arguments in a macro invocation must be the same as the number of parameters in the corresponding macro definition. During parameter substitution, any arguments remaining after all specified arguments have been substituted (including any separating commas) are combined into one argument called the variable argument.
173
The variable argument will replace any occurrence of the identifier __VA_ARGS__ in the replacement list. The following example illustrates this:
#define debug(...) debug("flag"); /* fprintf(stderr, __VA_ARGS__) Becomes fprintf(stderr, "flag"); */
Commas in the macro invocation argument list do not act as argument separators when they are: v In character constants v In string literals v Surrounded by parentheses The following line defines the macro SUM as having two parameters a and b and the replacement tokens (a + b):
#define SUM(a,b) (a + b)
This definition would cause the preprocessor to change the following statements (if the statements appear after the previous definition):
c = SUM(x,y); c = d * SUM(x,y);
Use parentheses to ensure correct evaluation of replacement text. For example, the definition:
#define SQR(c) ((c) * (c))
requires parentheses around each parameter c in the definition in order to correctly evaluate an expression like:
y = SQR(a + b);
Without parentheses in the definition, the correct order of evaluation is not preserved, and the preprocessor output is:
y = (a + b * a + b);
Arguments of the # and ## operators are converted before replacement of parameters in a function-like macro. Once defined, a preprocessor identifier remains defined and in scope independent of the scoping rules of the language. The scope of a macro definition begins at the definition and does not end until a corresponding #undef directive is encountered. If there is no corresponding #undef directive, the scope of the macro definition lasts until the end of the translation unit. A recursive macro is not fully expanded. For example, the definition
#define x(a,b) x(a+1,b+1) + 4
expands
x(20,10)
174
XL C Language Reference
to
x(20+1,10+1) + 4
rather than trying to expand the macro x over and over within itself. After the macro x is expanded, it is a call to function x(). A definition is not required to specify replacement tokens. The following definition removes all instances of the token debug from subsequent lines in the current file:
#define debug
You can change the definition of a defined identifier or macro with a second preprocessor #define directive only if the second preprocessor #define directive is preceded by a preprocessor #undef directive. The #undef directive nullifies the first definition so that the same identifier can be used in a redefinition. Within the text of the program, the preprocessor does not scan character constants or string constants for macro invocations. The following example program contains two macro definitions and a macro invocation that refers to both of the defined macros:
/** ** This example illustrates #define directives. **/ #include <stdio.h> #define SQR(s) ((s) * (s)) #define PRNT(a,b) \ printf("value 1 = %d\n", a); \ printf("value 2 = %d\n", b) ; int main(void) { int x = 2; int y = 3; PRNT(SQR(x),y); return(0); }
After being interpreted by the preprocessor, this program is replaced by code equivalent to the following:
#include <stdio.h> int main(void) { int x = 2; int y = 3; printf("value 1 = %d\n", ( (x) * (x) ) ); printf("value 2 = %d\n", y); return(0); }
175
Related information v Operator precedence and associativity on page 126 v Parenthesized expressions ( ) on page 98 Variadic macro extensions: IBM extension Variadic macro extensions refer to two extensions to C99 related to macros with variable number of arguments. One extension is a mechanism for renaming the variable argument identifier from __VA_ARGS__ to a user-defined identifier. The other extension provides a way to remove the dangling comma in a variadic macro when no variable arguments are specified. Both extensions have been implemented to facilitate porting programs developed with GNU C. The following examples demonstrate the use of an identifier in place of __VA_ARGS__. The first definition of the macro debug exemplifies the usual usage of __VA_ARGS__. The second definition shows the use of the identifier args in place of __VA_ARGS__.
#define debug1(format, ...) printf(format, __VA_ARGS__) #define debug2(format, args ...) printf(format, args) Invocation debug1("Hello %s\n","World"); debug2("Hello %s\n","World"); Result of Macro Expansion printf("Hello %s\n","World"); printf("Hello %s\n","World");
The preprocessor removes the trailing comma if the variable arguments to a function macro are omitted or empty and the comma followed by ## precedes the variable argument identifier in the function macro definition. End of IBM extension
If the identifier is not currently defined as a macro, #undef is ignored. The following directives define BUFFER and SQR:
#define BUFFER 512 #define SQR(x) ((x) * (x))
176
XL C Language Reference
Any occurrences of the identifiers BUFFER and SQR that follow these #undef directives are not replaced with any replacement tokens. Once the definition of a macro has been removed by an #undef directive, the identifier can be used in a new #define directive.
The # operator
The # (single number sign) operator converts a parameter of a function-like macro into a character string literal. For example, if macro ABC is defined using the following directive:
#define ABC(x) #x
all subsequent invocations of the macro ABC would be expanded into a character string literal containing the argument passed to ABC. For example:
Invocation ABC(1) ABC(Hello there) Result of Macro Expansion "1" "Hello there"
The # operator should not be confused with the null directive. Use the # operator in a function-like macro definition according to the following rules: v A parameter following # operator in a function- like macro is converted into a character string literal containing the argument passed to the macro. v White-space characters that appear before or after the argument passed to the macro are deleted. v Multiple white-space characters imbedded within the argument passed to the macro are replaced by a single space character. v If the argument passed to the macro contains a string literal and if a \ (backslash) character appears within the literal, a second \ character is inserted before the original \ when the macro is expanded. v If the argument passed to the macro contains a " (double quotation mark) character, a \ character is inserted before the " when the macro is expanded. v The conversion of an argument into a string literal occurs before macro expansion on that argument. v If more than one ## operator or # operator appears in the replacement list of a macro definition, the order of evaluation of the operators is not defined. v If the result of the macro expansion is not a valid character string literal, the behavior is undefined. The following examples demonstrate the use of the # operator:
#define STR(x) #define XSTR(x) #define ONE Invocation STR(\n "\n" \n) STR(ONE) XSTR(ONE) XSTR("hello") #x STR(x) 1 Result of Macro Expansion "\n \"\\n\" \\n" "ONE" "1" "\"hello\""
177
The ## operator
The ## (double number sign) operator concatenates two tokens in a macro invocation (text and/or arguments) given in a macro definition. If a macro XY was defined using the following directive:
#define XY(x,y) x##y
the last token of the argument for x is concatenated with the first token of the argument for y. Use the ## operator according to the following rules: v The ## operator cannot be the very first or very last item in the replacement list of a macro definition. v The last token of the item in front of the ## operator is concatenated with first token of the item following the ## operator. v Concatenation takes place before any macros in arguments are expanded. v If the result of a concatenation is a valid macro name, it is available for further replacement even if it appears in a context in which it would not normally be available. v If more than one ## operator and/or # operator appears in the replacement list of a macro definition, the order of evaluation of the operators is not defined. The following examples demonstrate the use of the ## operator:
#define #define #define #define #define #define #define ArgArg(x, y) ArgText(x) TextArg(x) TextText Jitter bug Jitterbug x##y x##TEXT TEXT##x TEXT##text 1 2 3 Result of Macro Expansion "ladybug" "conTEXT" "TEXTbook" "TEXTtext" 3
178
XL C Language Reference
where: Mmm dd yyyy __FILE__ Represents the month in an abbreviated form (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, or Dec). Represents the day. If the day is less than 10, the first d is a blank character. Represents the year.
A character string literal containing the name of the source file. The value of __FILE__ changes as the compiler processes include files that are part of your source program. It can be set with the #line directive.
__LINE__
An integer representing the current source line number. The value of __LINE__ changes during compilation as the compiler processes subsequent lines of your source program. It can be set with the #line directive.
__STDC__
For C, the integer 1 (one) indicates that the C compiler supports the ISO standard. If you set the language level to anything other than ANSI, this macro is undefined. (When a macro is undefined, it behaves as if it had the integer value 0 when used in a #if statement.)
__STDC_HOSTED__ The value of this C99 macro is 1, indicating that the C compiler is a hosted implementation. __STDC_VERSION__ The integer constant of type long int: 199409L for the C89 language level, 199901L for C99. __TIME__ A character string literal containing the time when the source file was compiled. The value of __TIME__ changes as the compiler processes any include files that are part of your source program. The time is in the form:
"hh:mm:ss"
where: hh mm ss Represents the hour. Represents the minutes. Represents the seconds.
Related information v The #line directive on page 186 v Object-like macros on page 172
179
In all C implementations, the preprocessor resolves macros contained in an #include directive. After macro replacement, the resulting token sequence must consist of a file name enclosed in either double quotation marks or the characters < and >. For example:
#define MONTH <july.h> #include MONTH
the preprocessor treats it as a user-defined file, and searches for the file in a manner defined by the preprocessor. If the file name is enclosed in angle brackets, for example:
#include <stdio.h>
it is treated as a system-defined file, and the preprocessor searches for the file in a manner defined by the preprocessor. The new-line and > characters cannot appear in a file name delimited by < and >. The new-line and " (double quotation marks) character cannot appear in a file name delimited by " and ", although > can. Declarations that are used by several files can be placed in one file and included with #include in each file that uses them. For example, the following file defs.h contains several definitions and an inclusion of an additional file of declarations:
/* defs.h */ #define TRUE 1 #define FALSE 0 #define BUFFERSIZE 512 #define MAX_ROW 66 #define MAX_COLUMN 80 int hour; int min; int sec; #include "mydefs.h"
You can embed the definitions that appear in defs.h with the following directive:
#include "defs.h"
In the following example, a #define combines several preprocessor macros to define a macro that represents the name of the C standard I/O header file. A #include makes the header file available to the program.
180
XL C Language Reference
#define C_IO_HEADER <stdio.h> /* The following is equivalent to: * #include <stdio.h> */ #include C_IO_HEADER
181
You can nest conditional compilation directives. In the following directives, the first #else is matched with the #if directive.
#ifdef MACNAME /* # # if TEST <=10 /* tokens added if MACNAME is defined and TEST <= 10 */ else /* tokens added if MACNAME is defined and TEST > # endif #else /* #endif tokens added if MACNAME is not defined */ 10 */ tokens added if MACNAME is defined */
Each directive controls the block immediately following it. A block consists of all the tokens starting on the line following the directive and ending at the next conditional compilation directive at the same nesting level. Each directive is processed in the order in which it is encountered. If an expression evaluates to zero, the block following the directive is ignored. When a block following a preprocessor directive is to be ignored, the tokens are examined only to identify preprocessor directives within that block so that the conditional nesting level can be determined. All tokens other than the name of the directive are ignored. Only the first block whose expression is nonzero is processed. The remaining blocks at that nesting level are ignored. If none of the blocks at that nesting level has been processed and there is a #else directive, the block following the #else directive is processed. If none of the blocks at that nesting level has been processed and there is no #else directive, the entire nesting level is ignored.
if elif
constant_expression
token_sequence
If the constant expression evaluates to a nonzero value, the lines of code that immediately follow the condition are passed on to the compiler. If the expression evaluates to zero and the conditional compilation directive contains a preprocessor #elif directive, the source text located between the #elif and the next #elif or preprocessor #else directive is selected by the preprocessor to be passed on to the compiler. The #elif directive cannot appear after the preprocessor #else directive. All macros are expanded, any defined() expressions are processed and all remaining identifiers are replaced with the token 0. The constant_expression that is tested must be integer constant expressions with the following properties: v No casts are performed.
182
XL C Language Reference
v Arithmetic is performed using long int values. v The constant_expression can contain defined macros. No other identifiers can appear in the expression. v The constant_expression can contain the unary operator defined. This operator can be used only with the preprocessor keyword #if or #elif. The following expressions evaluate to 1 if the identifier is defined in the preprocessor, otherwise to 0:
defined identifier defined(identifier)
For example:
#if defined(TEST1) || defined(TEST2)
Note: If a macro is not defined, a value of 0 (zero) is assigned to it. In the following example, TEST must be a macro identifier:
#if TEST >= 1 printf("i = %d\n", i); printf("array[i] = %d\n", array[i]); #elif TEST < 0 printf("array subscript out of bounds \n"); #endif
# ifdef identifier
token_sequence
newline_character
The following example defines MAX_LEN to be 75 if EXTENDED is defined for the preprocessor. Otherwise, MAX_LEN is defined to be 50.
#ifdef EXTENDED # define MAX_LEN 75 #else # define MAX_LEN 50 #endif
# ifndef identifier
token_sequence
newline_character
183
An identifier must follow the #ifndef keyword. The following example defines MAX_LEN to be 50 if EXTENDED is not defined for the preprocessor. Otherwise, MAX_LEN is defined to be 75.
#ifndef EXTENDED # define MAX_LEN 50 #else # define MAX_LEN 75 #endif
else
token_sequence
newline_character
184
XL C Language Reference
static int array[ ] = { 1, 2, 3, 4, 5 }; int i; for (i = 0; i <= 4; i++) { array[i] *= 2; #if TEST >= 1 printf("i = %d\n", i); printf("array[i] = %d\n", array[i]); #endif } return(0); }
# error
preprocessor_token
The #error directive is often used in the #else portion of a #if#elif#else construct, as a safety check during compilation. For example, #error directives in the source file can prevent code generation if a section of the program is reached that should be bypassed. For example, the directive
#define BUFFER_SIZE 255 #if BUFFER_SIZE < 256 #error "BUFFER_SIZE is too small." #endif
185
warning
preprocessor_token
The preprocessor #warning directive is a language extension provided to facilitate handling programs developed with GNU C. The IBM implementation preserves multiple white spaces. End of IBM extension
In order for the compiler to produce meaningful references to line numbers in preprocessed source, the preprocessor inserts #line directives where necessary (for example, at the beginning and after the end of included text). A file name specification enclosed in double quotation marks can follow the line number. If you specify a file name, the compiler views the next line as part of the specified file. If you do not specify a file name, the compiler views the next line as part of the current source file. At the C99 language level, the maximum value of the #line preprocessing directive is 2147483647. In all C implementations, the token sequence on a #line directive is subject to macro replacement. After macro replacement, the resulting character sequence must consist of a decimal constant, optionally followed by a file name enclosed in double quotation marks. You can use #line control directives to make the compiler provide more meaningful error messages. The following example program uses #line control directives to give each function an easily recognizable line number:
/** ** This example illustrates #line directives. **/
186
XL C Language Reference
#include <stdio.h> #define LINE200 200 int main(void) { func_1(); func_2(); } #line 100 func_1() { printf("Func_1 - the current line number is %d\n",_ _LINE_ _); } #line LINE200 func_2() { printf("Func_2 - the current line number is %d\n",_ _LINE_ _); }
Assertion directives
IBM extension An assertion directive is an alternative to a macro definition, used to define the computer or system the compiled program will run on. Assertions are usually predefined, but you can define them with the #assert preprocessor directive. #assert directive syntax
# assert predicate ( answer )
The predicate represents the assertion entity you are defining. The answer represents a value you are assigning to the assertion. You can make several assertions using the same predicate and different answers. All the answers for any given predicate are simultaneously true. For example, the following directives create assertions regarding font properties:
#assert font(arial) #assert font(blue)
Once an assertion has been defined, the assertion predicate can be used in conditional directives to test the current system. The following directive tests whether arial or blue is asserted for font:
#if #font(arial) || #font(blue)
You can test whether any answer is asserted for a predicate by omitting the answer in the conditional:
#if #font
187
Assertions can be cancelled with the #unassert directive. If you use the same syntax as the #assert directive, the directive cancels only the answer you specify. For example, the following directive cancels the arial answer for the font predicate:
#unassert font(arial)
An entire predicate is cancelled by omitting the answer from the #unassert directive. The following directive cancels the font directive altogether:
#unassert font
Predefined assertions
The following assertions are predefined for the AIX platform:
Table 22. Predefined assertions for AIX #machine #system(unix) #system(aix) #cpu
Pragma directives
A pragma is an implementation-defined instruction to the compiler. It has the general form: #pragma directive syntax
pragma STDC
character_sequence
new-line
The character_sequence is a series of characters giving a specific compiler instruction and arguments, if any. The token STDC indicates a standard pragma; consequently,
188
XL C Language Reference
no macro substitution takes place on the directive. The new-line character must terminate a pragma directive. The character_sequence on a pragma is subject to macro substitutions. For example,
#define XX_ISO_DATA isolated_call(LG_ISO_DATA) // ... #pragma XX_ISO_DATA
Note: You can also use the _Pragma operator syntax to specify a pragma directive; for details, see The _Pragma preprocessing operator on page 110. More than one pragma construct can be specified on a single pragma directive. The compiler ignores unrecognized pragmas.
IBM Standard C pragmas are described in Standard pragmas. Pragmas available for XL C are described in General purpose pragmas in the XL C Compiler Reference.
Standard pragmas
A standard pragma is a pragma preprocessor directive for which the C Standard defines the syntax and semantics and for which no macro replacement is performed. A standard pragma must be one of the following:
#pragma STDC FP_CONTRACT FENV_ACCESS CX_LIMITED_RANGE ON OFF DEFAULT new-line
The FP_CONTRACT and FENV_ACCESS pragmas are recognized and ignored. CX_LIMITED_RANGE is described below.
189
190
XL C Language Reference
191
Table 23. Default C99 features as extensions to C89 (continued) Language feature Empty arguments in function-like macros Additional predefined macro names Compound literals _Pragma operator Standard pragmas New limit for #line directive Discussed in: Function-like macros on page 173 Standard predefined macro names on page 178 Compound literals on page 102 The _Pragma preprocessing operator on page 110 Standard pragmas on page 189 The #line directive on page 186
The following feature is enabled by default when you compile with the xlc invocation command. It is also enabled with the options -qlanglvl=extc89 (the default in xlc), -qlanglvl=stdc99, -qlanglvl=extc99 and -qlanglvl=extended. It is also enabled or disabled by a specific compiler option, which is listed in the table below.
Table 24. Default C99 features as extensions to C89, with individual option controls Language feature Digraphs Discussed in: Digraph characters on page 26 Individual option control -q[no]digraph
The following features are enabled by default when you compile with the c99 invocation command, or with the-qlanglvl=stdc99 or -qlanglvl=extc99 compiler options or related pragmas. They are also enabled or disabled by specific compiler options, which are listed in the table below; these compiler options are enabled in the default configuration file for the xlc invocation command.
Table 25. Strict C99 features as extensions to C89, with individual option controls enabled by default for xlc in the configuration file Language feature C++ style comments The inline function specifier Discussed in: Comments on page 27 Individual option control -q[no]cpluscmt
The following features are enabled only when you compile with the c99 invocation command, or with the-qlanglvl=stdc99 or -qlanglvl=extc99 compiler options or related pragmas. They are also enabled by specific compiler options, listed in the table below.
Table 26. Strict C99 features as extensions to C89, with individual option controls Language feature Universal character names Discussed in: The Unicode standard on page 24 Individual option control -qlanglvl=[no]ucs -qkeyword=restrict
192
XL C Language Reference
The following feature is enabled only when you compile with the c99 invocation command, or with the-qlanglvl=stdc99 or -qlanglvl=extc99 compiler options or related pragmas.
Language feature Unsuffixed long long integer literals Discussed in: Decimal integer literals on page 13
Related information v -qcpluscmt, -qkeyword, and -qdigraph in the XL C Compiler Reference v How to choose a compiler invocation in the XL C Compiler Reference
Static initialization of flexible array members Flexible array members on page 46 of aggregates Zero-extent arrays Type attributes Variable attributes Locally declared labels Labels as values __alignof__ operator Zero-extent array members on page 47 Type attributes on page 61 Variable attributes on page 83 Locally declared labels on page 132 Labels as values on page 132 The __alignof__ operator on page 107
Appendix A. The IBM XL C language extensions
193
Table 27. Default IBM XL C extensions for GNU C compatibility (continued) Language feature __typeof__ operator Generalized lvalues Discussed in: The typeof operator on page 109 Lvalues and rvalues on page 95
Complex type arguments to unary operators Unary expressions on page 102 Initialization of static variables by compound literals __imag__ and __real__ complex type operators Cast to a union type Computed goto statements Statements and declarations in expressions Function attributes __inline__ function specifier Nested functions Variadic macro extensions #warning preprocessor directive #include_next preprocessor directive #assert, #unassert preprocessor directives Compound literals on page 102 The __real__ and __imag__ operators on page 111 Cast to union type (C only) on page 112 Computed goto statement on page 148 Statement expressions on page 134 Function attributes on page 162 The inline function specifier on page 157 Nested functions on page 170 Variadic macro extensions on page 176 The #warning directive on page 186 The #include_next directive on page 181 Assertion directives on page 187
The following features are enabled by default when you compile with the xlc invocation command. They are also enabled with the options -qlanglvl=extc89 (the default in xlc), -qlanglvl=extc99, and -qlanglvl=extended. They can also be enabled and disabled by specific compiler options, which are listed in the table below.
Table 28. IBM XL C extensions for GNU C compatibility with individual option controls Language feature typeof, asm, and __asm keywords Discussed in: The typeof operator on page 109, Assembly labels on page 10, Inline assembly statements on page 149 Inline assembly statements on page 149 Individual option controls -qkeyword
-qasm
The following feature requires compilation with the use of an additional option.
Table 29. IBM XL C extensions for GNU C compatibility, requiring additional compiler options Language feature Dollar signs in identifiers Discussed in: Required compilation option
194
XL C Language Reference
The following features are IBM extensions to the AltiVec Application Programming Interface specification.
Table 31. IBM XL C extensions to the AltiVec Application Programming Interface specification Language extension Initializer lists for vector constants typedef definitions for vector types compound literals as initializers for static vector variables vector types as arguments to the __alignof__ and typeof operators Discussed in: Initialization of vectors on page 77 typedef definitions on page 54 Compound literals on page 102 The __alignof__ operator on page 107, The typeof operator on page 109
195
196
XL C Language Reference
The compiler considers any long vector data type compatible with the corresponding int vector type. Note: The long vector types are deprecated. The following table shows the supported vector literals and how the compiler interprets them to determine their values.
197
Table 33. Vector literals Syntax (vector unsigned char)(single unsigned int value) (vector unsigned char)(unsigned int value, ..., unsigned int value) (vector signed char)(single int value) (vector signed char)(int value, ..., int value) (vector bool char)(single unsigned int) Interpreted by the compiler as A set of 16 unsigned constants with a value specified by the integer constant expression. A set of 16 unsigned constants with a value specified by the 16 integer constant expressions. A set of 16 signed constants with a value specified by the integer constant expression. A set of 16 signed constants with a value specified by the 16 integer constant expressions. A set of 16 unsigned constants with a value specified by the integer constant expression.
(vector bool char)(unsigned int value, ..., unsigned int value) A set of 16 unsigned constants with a value specified by the 16 integer constant expressions. (vector unsigned short)(single unsigned int value) (vector unsigned short)(unsigned int value, ..., unsigned int value) (vector signed short)(single int value) (vector signed short)(int value, ..., int value) (vector bool short)(single unsigned int value) (vector bool short)(unsigned int value, ..., unsigned int value) (vector unsigned int)(single unsigned int value) (vector unsigned int)(unsigned int value, ..., unsigned int value) (vector signed int)(single int value) (vector signed int)(int value, ..., int value) (vector bool int)(single unsigned int value) (vector bool int)(unsigned int value, ..., unsigned int value) (vector float)(single float value) (vector float)(float value, ... float value) (vector pixel)(single unsigned int value) (vector pixel)(unsigned int value, ..., unsigned int value) A set of 8 unsigned constants with a value specified by the integer constant expression. A set of 8 unsigned constants with a value specified by the 8 integer constant expressions. A set of 8 signed constants with a value specified by the integer constant expression. A set of 8 signed constants with a value specified by the 8 integer constant expressions. A set of 8 unsigned constants with a value specified by the integer constant expression. A set of 8 unsigned constants with a value specified by the 8 integer constant expressions. A set of 4 unsigned constants with a value specified by the integer constant expression. A set of 4 unsigned constants with a value specified by the 4 integer constant expressions. A set of 4 signed constants with a value specified by the integer constant expression. A set of 4 signed constants with a value specified by the 4 integer constant expressions. A set of 4 unsigned constants with a value specified by the integer constant expression. A set of 4 unsigned constants with a value specified by the 4 integer constant expressions. A set of 4 floating-point constants with a value specified by the floating-point constant expression. A set of 4 floating-point constants with a value specified by the 4 floating-point constant expressions. A set of 8 unsigned constants with a value specified by the integer constant expression. A set of 8 unsigned constants with a value specified by the 8 integer constant expressions.
198
XL C Language Reference
A
addition operator (+) 114 address operator (&) 105 GNU C extension 132 aggregate types 31 initialization 78 alias function 10 type-based aliasing 69 alignment 85, 86 bit fields 48 structure members 45 structures 85 structures and unions 59 alignof operator 107 AND operator, bitwise (&) 118 AND operator, logical (&&) 119 argc (argument count) 167 example 167 arguments macro 173 main function 167 passing 153, 168 passing by reference 169 passing by value 168 trailing 173, 176 argv (argument vector) 167 example 167 arithmetic conversions 89 arithmetic types type compatibility 43 arrays array-to-pointer conversions 92 as function parameter 36, 161 declaration 36, 161 description 70 flexible array member 45, 46 initialization 75 initializing 81 multidimensional 71 subscripting operator 100 type compatibility 73 variable length 67, 72 zero-extent 45, 47 ASCII character codes 23 asm 7 keyword 10, 38 labels 10 statements 149 assembly labels 10 statements 149 assignment operator (=) compound 124 pointers 70 simple 123 associativity of operators 126 auto storage class specifier 35
B
binary expressions and operators 113 bit fields 47 as structure member 45 type name 110 bitwise negation operator (~) 105 block statement 133 block visibility 2 bool 43 Boolean conversions 89, 90 data types 40 literals 14 break statement 144 built-in data types 31
C
case label 136 cast expressions 18, 44, 111 complex to real 90 union type 112 char type specifier 41 character data types 41 literals 18 multibyte 20, 22 character set extended 22 source 22 class members access operators 101 classes class objects 31 comma 125 in enumerator list 51 comments 27 compatibility C89 and C99 191 data types 32 user-defined types 53 XL C and GCC viii, 193 compatible types across source files 54 arithmetic types 43 arrays 73 in conditional expressions 121 vector types 43 complex types 41 composite types 32 across source files 54 compound assignment 124 literal 99, 102 statement 133 types 31 computed goto 110, 132, 148 concatenation macros 178 multibyte characters 20
199
concatenation (continued) u-literals, U-literals 25 conditional compilation directives 181 elif preprocessor directive 182 else preprocessor directive 184 endif preprocessor directive 184 examples 184 if preprocessor directive 182 ifdef preprocessor directive 183 ifndef preprocessor directive 183 conditional expression (? :) 121 const 43, 57 function attribute 164 object 95 placement in type name 67 qualifier 56 vs. #define 172 constant expressions 51, 98 continuation character 20, 171 continue statement 144 conversions arithmetic 89 array-to-pointer 92 Boolean 89, 90 cast 111 floating-point 90 function arguments 93 function-to-pointer 93 integral 89 lvalue-to-rvalue 92, 95 pointer 92 standard 89 void pointer 93 cv-qualifier 56 syntax 56
decrement operator () 104 default clause 136, 137 label 137 define preprocessor directive 172 defined unary operator 182 definitions description 33 macro 172 tentative 34 dereferencing operator 106 derivation array type 71 designated initializer aggregate types 75 union 78 designator 75 designation 75 designator list 75 union 78 digraph characters 26 division operator (/) 114 do statement 141 dollar sign 9, 22 dot operator 101 double type specifier 41
exponent 14 expressions assignment 123 binary 113 cast 111 comma 125 conditional 121 description 95 integer constant 98 parenthesized 98 primary 97 statement 133 unary 102 extern storage class specifier 6, 37, 156 with function pointers 169 with variable length arrays 72
F
file inclusion 180, 181 FILE macro 179 file scope data declarations unsubscripted arrays 72 flexible array member 46 float type specifier 41 floating-point constant 15 conversion 90 literal 14 promotion 91 floating-point types 41 for statement 142 function aliases 10 function attributes 162 function designator 95 function-like macro 173 functions 153 arguments 153, 168 conversions 93 block 153 body 153 calling 168 calls 99 as lvalue 95 declaration 153 examples 155 parameter names 161 definition 153 examples 155 function call operator 153 function-to-pointer conversions inline 157 library functions 153 main 167 name 153 diagnostic 10 parameters 168 pointers to 169 predefined identifier 10 prototype 153 return statements 145 return type 153, 159 return value 153, 159 specifiable attributes 162 specifiers 157 type name 67
E
EBCDIC character codes 24 elif preprocessor directive 182 ellipsis in function declaration 161 in function definition 161 in macro argument list 173 else preprocessor directive 184 statement 135 endif preprocessor directive 184 entry point program 167 enum keyword 51 enumerations 51 compatibility 53, 54 declaration 51 initialization 80 trailing comma 51 enumerator 52 equal to operator (==) 117 error preprocessor directive 185 escape character \ 23 escape sequence 23 alarm \a 23 backslash \\ 23 backspace \b 23 carriage return \r 23 double quotation mark \ 23 form feed \f 23 horizontal tab \t 23 new-line \n 23 question mark \? 23 single quotation mark \ 23 vertical tab \v 23 exclusive OR operator, bitwise (^) explicit type conversions 111
D
data types aggregates 31 Boolean 40 built-in 31 character 41 compatible 32 complex 41 composite 32 compound 31 enumerated 51 floating 41 incomplete 32 integral 39 scalar 31 user-defined 31, 44 vector 43 void 42 DATE macro 178 decimal integer literals 13 declaration 153 declarations description 33 duplicate type qualifiers 56 syntax 34, 67, 154 unsubscripted arrays 72 vector types 43 declarative region 1 declarators description 65
93
118
200
XL C Language Reference
G
global register variables 38 global variable 3, 6 uninitialized 74 goto statement 147 computed goto 148 restrictions 147 greater than operator (>) 116 greater than or equal to operator (>=) 116
inline (continued) functions 157 integer constant expressions conversion 89 conversions 89 data types 39 literals 12 promotion 91
M
51, 98 macro definition 172 typeof operator 110 function-like 173 invocation 173 object-like 172 variable argument 173, 176 main function 167 arguments 167 example 167 members class member access operators modifiable lvalue 95, 123 modulo operator (%) 114 multibyte character 22 concatenation 20 multicharacter literal 18 multidimensional arrays 71 multiplication operator (*) 113
K H
hexadecimal floating constants 15 hexadecimal integer literals 13 keywords 7 language extension 8 underscore characters 8
101
L I
identifiers 8, 97 case sensitivity 9 labels 131 linkage 6 namespace 4 predefined 10 reserved 7, 8, 9 special characters 9, 22 if preprocessor directive 182 statement 135 ifdef preprocessor directive 183 ifndef preprocessor directive 183 implementation dependency allocation of floating-point types 41 implicit conversion 89 boolean 90 Boolean 89 lvalue 95 types 89 include preprocessor directive 180 include_next preprocessor directive 181 inclusive OR operator, bitwise (|) 119 incomplete type 71 as structure member 45, 46 incomplete types 32 increment operator (++) 103 indentation of code 171 indirection operator (*) 43, 106 information hiding 1, 2 initialization aggregate types 78 auto object 74 extern object 74 register object 75 static object 74, 102 union member 80 vector types 77 initializer lists 73, 77, 102 initializers 73 aggregate types 75, 78 enumerations 80 unions 80 vector types 77 inline assembly statements 149 function specifier 157 label as values 132 implicit declaration 3 in switch statement 137 locally declared 132 statement 131 language extension viii, 8 C99 191 GNU C viii, 191 left-shift operator (<<) 115 less than operator (<) 116 less than or equal to operator (<=) 116 LINE macro 179 line preprocessor directive 186 linkage 1, 5 auto storage class specifier 35 const cv-qualifier 57 extern storage class specifier 37 external 6 in function definition 156 internal 5, 36, 156 none 6 register storage class specifier 38 static storage class specifier 36 weak symbols 86 with function pointers 169 literals 11 Boolean 14 character 18 compound 99, 102 floating-point 14 integer 12 decimal 13 hexadecimal 13 octal 13 string 19 Unicode 25 logical operators ! (logical negation) 105 || (logical OR) 120 && (logical AND) 119 long double type specifier 41 long long type specifier 40, 43 long type specifier 39, 43 lvalues 56, 95, 97 casting 111 conversions 92, 95
N
names conflicts 4 resolution 2 namespace context 5 of identifiers 4 narrow character literal 18 not equal to operator (!=) 117 null character \0 20 pointer 81 pointer constants 92 preprocessor directive 188 statement 148 number sign (#) preprocessor directive character preprocessor operator 177
171
O
object-like macro 172 objects 95 description 31 lifetime 1 restrict-qualified pointer 58 octal integer literals 13 ones complement operator (~) 105 operators 21 - (subtraction) 115 -- (decrement) 104 -> (arrow) 101 , (comma) 125 ! (logical negation) 105 != (not equal to) 117 ? : (conditional) 121 / (division) 114 . (dot) 101 () (function call) 99, 153 * (indirection) 106 * (multiplication) 113 (unary minus) 104 [] (array subscripting) 100 % (remainder) 114 Index
201
operators (continued) > (greater than) 116 >> (right- shift) 115 >= (greater than or equal to) 116 < (less than) 116 << (left- shift) 115 <= (less than or equal to) 116 | (bitwise inclusive OR) 119 || (logical OR) 120 & (address) 105 & (bitwise AND) 118 && (logical AND) 119 + (addition) 114 ++ (increment) 103 = (simple assignment) 123 == (equal to) 117 ^ (bitwise exclusive OR) 118 alternative representations 21 assignment 123 associativity 126 binary 113 bitwise negation operator (~) 105 compound assignment 124 defined 182 equality 117 expressions 99 operators 99 precedence 126 examples 128 type names 67 preprocessor # 177 ## 178 pragma 110 relational 116 sizeof 108 typeof 109 unary 102 unary plus operator (+) 104 OR operator, logical (||) 120
pound sign (#) preprocessor directive character 171 preprocessor operator 177 pragma operator 110 pragmas _Pragma 110 preprocessor directive 188 standard 189 precedence of operators 126 predefined identifier 10 predefined macros DATE 178 FILE 179 LINE 179 STDC 179 STDC_HOSTED 179 STDC_VERSION 179 TIME 179 prefix ++ and -- 103, 104 hexadecimal floating constants 15 hexadecimal integer literals 13 octal integer literals 13 preprocessor directives 171 conditional compilation 181 preprocessing overview 171 special character 171 warning 186 preprocessor operator _Pragma 110 # 177 ## 178 primary expressions 97 promotions integral and floating-point 91 punctuators 21 alternative representations 21
Q
qualifiers const 56 restrict 58 volatile 56, 57
P
packed structure member 47 variable attribute 86 parenthesized expressions 67, 98 pass by reference 169 pass by value 168 pixel 43 pointers conversions 92 cv-qualified 68 dereferencing 69 description 68 generic 93 null 81 pointer arithmetic 43, 68 restrict-qualified 58 to functions 169 type-qualified 68 vector types 43 void* 92 postfix ++ and -- 103, 104 expression 99 operator 99
R
references as return types 159 register storage class specifier register variables 38 remainder operator (%) 114 restrict 58 return statement 145, 159 return type reference as 159 size_t 108 right-shift operator (>>) 115 rvalues 95 37
S
scalar types 31, 68 scope 1 description 1 enclosing and nested 2
scope (continued) function 3 function prototype 3 global 3 identifiers 4 local (block) 2 macro names 176 sequence point 125 shift operators << and >> 115 short type specifier 39 side effect 58 signed type specifiers char 41 int 39 long 39 long long 39 size_t 108 sizeof operator 108 with variable length arrays 73 space character 171 special characters 22 specifiers inline 157 storage class 35 splice preprocessor directive ## 178 standard type conversions 89 statement expression 134 statements 131 block 133 break 144 compound 134 continue 144 do 141 expressions 133 for 142 goto 147 if 135 labels 131 null 148 return 145, 159 selection 135, 136 switch 136 while 140 static 43 in array declaration 36, 161 storage class specifier 36, 156 linkage 36 with variable length arrays 72 static storage class specifier 6 STDC macro 179 STDC_HOSTED macro 179 STDC_VERSION macro 179 storage class specifiers 35 auto 35 extern 37, 156 register 37 static 36, 156 storage duration 1 auto storage class specifier 35 extern storage class specifier 37 register storage class specifier 38 static 36, 156 string literal 19 terminator 20 stringize preprocessor directive # 177 struct type specifier 45
202
XL C Language Reference
structures 44 alignment 59 compatibility 53, 54 flexible array member 45, 46 identifier (tag) 45 initialization 78 members 45 alignment 45 incomplete types 46 layout in memory 45, 78 packed 47 padding 45 zero-extent array 45 namespaces within 5 packed 45 unnamed members 78 subscript declarator in arrays 71 subscripting operator 70, 100 in type name 67 subtraction operator () 115 suffix floating-point literals 14 hexadecimal floating constants integer literal constants 12 switch statement 136
typedef specifier 54 with variable length arrays typeof operator 109 types conversions 111 type-based aliasing 69 variably modified 71
73
while statement 140 white space 7, 27, 171, 177 wide characters literals 18 wide string literal 20
Z
zero-extent array 47
U
u-literal, U-literal 25 unary expressions 102 unary operators 102 label value 110 minus () 104 plus (+) 104 undef preprocessor directive 176 underscore character 8, 9 Unicode 24 unions 44 cast to union type 112 compatibility 53, 54 designated initializer 75 initialization 80 specifier 45 unnamed members 78 universal character name 9, 19, 24 unsigned type specifiers char 41 int 39 long 39 long long 39 short 39 unsubscripted arrays description 72, 161 user-defined data types 31, 44 UTF-16, UTF-32 25
15
T
tags enumeration 51 structure 45 union 45 tentative definition 34 TIME macro 179 tokens 7, 171 alternative representations for operators and punctuators 21 translation unit 1 trigraph sequences 26 truncation integer division 114 type attributes 61 type name 66 typeof operator 109 type qualifiers const 56, 57 duplicate 56 restrict 56, 58 volatile 56 type specifier overriding 86 type specifiers 39 _Bool 40 (long) double 41 char 41 complex 41 enumeration 51 float 41 int 39 long 39 long long 39 short 39 unsigned 39 vector data types 43 void 42 wchar_t 39, 41
V
variable in specified registers 38 variable attributes 83 variable length array 32, 72, 147 as function parameter 73 sizeof 98 type name 67 variably modified types 71, 72, 138 vector data types 43 vector types 109, 197 in typedef declarations 55 literals 17, 197 visibility 1 block 2 VMX support viii, 195 void 42 in function definition 159, 161 pointer 92, 93 volatile qualifier 56, 57
W
warning preprocessor directive 186 wchar_t type specifier 18, 39, 41 weak symbol 86 Index
203
204
XL C Language Reference
Notices
This information was developed for products and services offered in the U.S.A. IBM may not offer the products, services, or features discussed in this document in other countries. Consult your local IBM representative for information on the products and services currently available in your area. Any reference to an IBM product, program, or service is not intended to state or imply that only that IBM product, program, or service may be used. Any functionally equivalent product, program, or service that does not infringe any IBM intellectual property right may be used instead. However, it is the users responsibility to evaluate and verify the operation of any non-IBM product, program, or service. IBM may have patents or pending patent applications covering subject matter described in this document. The furnishing of this document does not give you any license to these patents. You can send license inquiries, in writing, to: IBM Director of Licensing IBM Corporation North Castle Drive Armonk, NY 10504-1785 U.S.A. For license inquiries regarding double-byte (DBCS) information, contact the IBM Intellectual Property Department in your country or send inquiries, in writing, to: IBM World Trade Asia Corporation Licensing 2-31 Roppongi 3-chome, Minato-ku Tokyo 106, Japan The following paragraph does not apply to the United Kingdom or any other country where such provisions are inconsistent with local law: INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or implied warranties in certain transactions, therefore, this statement may not apply to you. This information could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes will be incorporated in new editions of the publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication at any time without notice. Any references in this information to non-IBM Web sites are provided for convenience only and do not in any manner serve as an endorsement of those Web sites. The materials at those Web sites are not part of the materials for this IBM product and use of those Web sites is at your own risk. IBM may use or distribute any of the information you supply in any way it believes appropriate without incurring any obligation to you.
Copyright IBM Corp. 1998, 2005
205
Licensees of this program who wish to have information about it for the purpose of enabling: (i) the exchange of information between independently created programs and other programs (including this one) and (ii) the mutual use of the information which has been exchanged, should contact: Lab Director IBM Canada Ltd. Laboratory B3/KB7/8200/MKM 8200 Warden Avenue Markham, Ontario L6G 1C7 Canada Such information may be available, subject to appropriate terms and conditions, including in some cases, payment of a fee. The licensed program described in this document and all licensed material available for it are provided by IBM under terms of the IBM Customer Agreement, IBM International Program License Agreement or any equivalent agreement between us. Information concerning non-IBM products was obtained from the suppliers of those products, their published announcements or other publicly available sources. IBM has not tested those products and cannot confirm the accuracy of performance, compatibility or any other claims related to non-IBM products. Questions on the capabilities of non-IBM products should be addressed to the suppliers of those products. This information contains examples of data and reports used in daily business operations. To illustrate them as completely as possible, the examples include the names of individuals, companies, brands, and products. All of these names are fictitious and any similarity to the names and addresses used by an actual business enterprise is entirely coincidental. COPYRIGHT LICENSE: This information contains sample application programs in source language, which illustrates programming techniques on various operating platforms. You may copy, modify, and distribute these sample programs in any form without payment to IBM, for the purposes of developing, using, marketing or distributing application programs conforming to the application programming interface for the operating platform for which the sample programs are written. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. You may copy, modify, and distribute these sample programs in any form without payment to IBM for the purposes of developing, using, marketing, or distributing application programs conforming to IBMs application programming interfaces.
206
XL C Language Reference
However, this information may also contain diagnosis, modification, and tuning information. Diagnosis, modification, and tuning information is provided to help you debug your application software. Note: Do not use this diagnosis, modification, and tuning information as a programming interface because it is subject to change.
Industry standards
The following standards are supported: v The C language is consistent with the International Standard for Information Systems-Programming Language C (ISO/IEC 9899-1999 (E)). v The C language is consistent with the OpenMP C Application Programming Interface Version 2.5.
Notices
207
208
XL C Language Reference
SC09-8004-00