The GNU C Reference Manual


Next: , Previous: (dir), Up: (dir)


Next: , Previous: Top, Up: Top

Preface

CAUTION: THIS MANUAL IS CURRENTLY BEING DEVELOPED, AND MAY CONTAIN NON-TRIVIAL ERRORS, OMISSIONS, AND INCONSISTENCIES.

This is a reference manual for the GNU C programming language: the C programming language as implemented by the GNU C compiler.

GCC supports several variants of C; this manual aims to explicitly document three of them:

By default, GCC will compile code as C89 plus GNU-specific extensions. Much of C99 is supported; once full support is available, the default compilation dialect will be C99 plus GNU-specific extensions. (Note that some of the GNU extensions to C89 found ended up, sometimes slightly modified, as standard language features in C99.)

Except as specified, this manual describes C89. Language features that are available only in C99 or as a GNU extension are labelled as such.

The C language includes a set of preprocessor directives, which are used for things such as macro text replacement, conditional compilation, and file inclusion. Although normally described in a C language manual, the GNU C preprocessor has been thoroughly documented in The C Preprocessor, a separate manual which covers preprocessing for C, C++, and Objective C programs.

Most of this manual was written by Trevis J. Rothwell, with contributions from Richard M. Stallman.

Other people have also contributed to this manual, either by way of editing, proofreading, making suggestions, fixing typesetting problems, and/or helping with administrative details. These individuals include: Robert J. Chassell, Lisa Goldstein, Robert J. Hansen, Joe Humphries, J. Wren Hunt, Steve Morningthunder, and Ole J. Tetlie.

This manual is (still) in progress; please feel free to send comments to Trevis Rothwell via email.


Next: , Previous: Preface, Up: Top

1 Lexical Elements

This chapter descibes the lexical elements that make up C source code after preprocessing. These basic elements are called tokens, and there are several distinct types of tokens: keywords, identifiers, constants, operators, and separators. White space, sometimes required to separate tokens, is also described in this chapter.


Next: , Previous: Lexical Elements, Up: Lexical Elements

1.1 Identifiers

Identifiers are strings of characters used for naming variables, functions, new data types, and preprocessor macros. The characters can be letters, decimal digits, the underscore character _, or the dollar sign character $.

The first character of an identifier cannot be a digit.

Lowercase letters and uppercase letters are distinct, so squid and SQUID are two different identifiers.


Next: , Previous: Identifiers, Up: Lexical Elements

1.2 Keywords

Keywords are special identifiers, reserved for use by the progamming language itself. You cannot use them for any other purpose, except for identifiers for preprocessor macros. Since the preprocessor replaces its macros' identifiers with the code they expand to before lexical processing begins, there is no interference.

Here is a list of keywords recognized by ANSI C89:

ISO C99 adds the following keywords:


Next: , Previous: Keywords, Up: Lexical Elements

1.3 Constants

A constant is a literal numeric or character value, such as 5 or `m'. All constants are of a specific data type; you can explicitly specify the type of a constant, or let the compiler use the default type based on the value of the constant.


Next: , Previous: Constants, Up: Constants

1.3.1 Integer Constants

An integer constant is a sequence of digits.

If the sequence of digits is preceded by 0x or 0X (zero x or zero X), then it is assumed to be hexadecimal (base 16). Hexadecimal values may use the digits from 0 to 9, as well as the letters a to f, or A to F.

     0x2F
     0x88
     0xAB43
     0x1

If the first digit is 0 (zero), and the second digit is not x or X, then the sequence of digits is assumed to be octal (base 8). Octal values may only use the digits from 0 to 7; 8 and 9 are not allowed.

     057
     012
     03
     0841

A 0 (zero) by itself is an octal value. If you want to make the octal properties of 0 obvious in your code, you might want to use two of them: 00.

In all other cases, the sequence of digits is assumed to be decimal (base 10). Decimal values may use the digits from 0 to 9.

     459
     23901
     8
     12

There are various integer data types, such as int, unsigned int, and long int. You can append a sequence of one or more letters to the end of an integer constant to cause it to be of a certain integer data type. The letters that you can use (and their meanings) are:

u
U
Unsigned integer type.
l
L
Long integer type.

For example, 45U is an unsigned int constant. You can also combine letters: 45UL is an unsigned long int constant. (The letters may be used in any order.) You can use two L's to get a long long int constant; add a U and you have an unsigned long long int constant.

There is no way to force an integer constant to be interpreted a short integer. In addition, an integer constant will never be interpreted as a short integer by default, even if its value is small enough to be represented as one. (Admittedly, this seems kind of unfair to the short integer community.)


Next: , Previous: Integer Constants, Up: Constants

1.3.2 Character Constants

A character constant is a sequence of one or more characters enclosed within single quotation marks, such as 'Q'. A character constant is of type int.

Some characters, such as the single quotation mark character ' itself, cannot be represented using only one character. To represent such characters, there are several “escape sequences” that you can use:

\\
Backslash character.
\?
Question mark character.
\'
Single quotation mark.
\"
Double quotation mark.
\a
Audible alert.
\b
Backspace character.
\e
<ESC> character.
\f
Form feed.
\n
Newline character.
\r
Carriage return.
\t
Horizontal tab.
\v
Vertical tab.
\ooo
Octal number.
\xhh
Hexadecimal number.

To use any of these escape sequences, enclose the sequence in single quotes, and treat it is if it were any other character. For example, the letter m is 'm' and the newline character is '\n'.

The octal number escape sequence is the backslash character followed by one, two, or three octal digits (0 to 7). For example, 101 is the octal equivalent of 65, which is the ASCII character 'A'. Thus, the character constant '\101' is the same as the character constant 'A'.

The hexadecimal escape sequence is the backslash character, followed by x and an unlimited number of hexadecimal digits (0 to 9, and a to f or A to F).

Since we are dealing with character constants, and the number of hexadecimal digits is unlimited, but the range of characters is not, please use some common sense. There is no need to refer to the 394,203,192,245th character if there are only 256 characters to choose from. If you try to use a hexadecimal value that is outside the range of characters, you will get a compile-time error.

You can make a character constant a “wide” character by appending the letter L to it, outside of the quotation marks. For example, L'm', and is of the data type wchar_t (defined in the <stddef.h> header file).


Next: , Previous: Character Constants, Up: Constants

1.3.3 Real Number Constants

A real number constant is a value that represents a fractional (floating point) number. It consists of a sequence of digits which represents the integer (or “whole”) part of the number, a decimal point, and a sequence of digits which represents the fractional part.

The integer part and the fractional part are not both required. If you leave out the integer part, then the decimal point is necessary. If you leave out the decimal part, then the decimal point is optional. You can't leave out both the integer and the decimal parts; that would cause a compile time error, and it would be a rather strange thing to do anyway. Here are some examples:

     /* Assigning real number constants to variables. */
     
     double a, b, c, d, e, f;
     
     a = 4.7;     /* This is okay. */
     
     b = 4.;      /* This is okay. */
     
     c = 4;       /* This is okay. */
     
     d = .7;      /* This is okay. */
     
     e = 0.7;     /* This is okay. */
     
     f = .;       /* This is NOT okay! */

Real number constants can also be followed by e or E, and an integer exponent. The exponent can be either positive or negative, but you can't leave it out.

     /* Assigning a real number constant with exponent. */
     
     double x, y;
     
     x = 5e2;   /* x is 500.0. */
     y = 5e-2;  /* y is 0.05. */

You can append a letter to the end of a real number constant to cause it to be of a certain data type. If you append the letter F (or f) to a real number constant, then its type is float. If you append the letter L (or l), then its type is long double. If you do not append any letters, then its type is double.


Previous: Real Number Constants, Up: Constants

1.3.4 String Constants

A string constant, or string literal, is a sequence of characters, digits, and/or escape sequences enclosed within double quotation marks. A string constant is of type “array of characters”.

Adjacent string constants are concatenated (combined) into one string, with the null character \0 added to the end of the string. The null character is used to indicate where the string ends. All string constants contain the null character as their last character, even if it is not explicitly stated.

A string cannot contain double quotation marks, as double quotation marks are used to enclose the string. To include the double quotation mark character in a string, use the \" escape sequence. You can use any of the escape sequences that can be used as character constants in strings. Here are some example of string literals:

     /* This is a single string constant. */
     "tutti frutti ice cream"
     
     /* These three string constant will be concatenated. */
     "pistachio " "ice " "cream"
     
     /* This one uses two escape sequences. */
     "\"hello, world!\""

If a string is too long to fit on one line, you can use a slash / to break it up onto separate lines.

     /* This is not a valid string. */
     "Today's special is a pastrami sandwich on rye bread with
     a potato knish and a cherry soda."
     
     /* This is valid. */
     "Today's special is a pastrami sandwich on rye bread with /
     a potato knish and a cherry soda."

The slash / works, but you have another option. Adjacent strings are automatically concatenated, so you can have strings span multiple lines by writing them as several separate, yet adjacent, strings. For example:

     "Tomorrow's special is a corned beef sandwich on "
     "pumpernickel bread with a kasha knish and seltzer water."

is the same as

     "Tomorrow's special is a corned beef sandwich on /
     pumpernickel bread with a kasha knish and seltzer water."

To force a newline character into the string, so that when the string is printed it will be printed on two different lines, you can use the newline escape sequence \n.

     printf ("potato\nknish");

prints

     potato
     knish

You can use wide characters in a string by using the L prefix, such as L"chocolate". If a string uses wide characters, then its data type is “array of wchar_t”. You can concatenate wide strings with non-wide strings, and the resulting string is a wide string.


Next: , Previous: Constants, Up: Lexical Elements

1.4 Operators

An operator is a token that performs an operation, such as addition or subtraction, on either one, two, or three operands. Many operators are one character long; some are longer. Full coverage of operators can be found in a later chapter, but here are some examples: +, -, >=, and ||. See Expressions and Operators.


Next: , Previous: Operators, Up: Lexical Elements

1.5 Separators

A separator is a token that is used to separate parts of an expression. White space is a separator, but it is not a token. The other separators are:

     ( ) [ ] { } ; , . :


Previous: Separators, Up: Lexical Elements

1.6 White Space

White space is the collective term used for a number of characters, including the space character, the tab character, and the newline character. In C programs, white space is ignored, and is therefore optional, except when it is used to separate tokens. This means that

     #include <stdio.h>
     
     int
     main()
     {
       printf( "hi there\n" );
       return 0;
     }

and

     #include <stdio.h> int main(){printf("hi there\n");
     return 0;}

are functionally the same program.

Although you must use white space to separate many tokens, no white space is required between operators and operands, nor is it required between separators and that which they separate.

     /* All of these are valid. */
     
     x++;
     x ++ ;
     x=y+z;
     x = y + z ;
     x=array[2];
     x = array [ 2 ] ;
     fraction=numerator/*denominator_ptr;
     fraction = numerator / * denominator_ptr ;

Furthermore, wherever one space is allowed, any white space is allowed.

     /* These two statements are functionally identical. */
     x++;
     
     x
            ++       ;

In string constants, spaces and tabs are not ignored; rather, they are part of the string. Therefore,

     "potato knish"

is not the same as

     "potato                        knish"


Next: , Previous: Lexical Elements, Up: Top

2 Data Types


Next: , Previous: Data Types, Up: Data Types

2.1 Primitive Data Types


Next: , Previous: Primitive Types, Up: Primitive Types

2.1.1 Integer Types

The integer data types range in size from at least 8 bits to at least 64 bits. You should use them for storing whole number values (and the char data type for storing characters). (Note that the sizes and ranges listed for these types are minimums; your particular compiler may allow for larger values.)


Next: , Previous: Integer Types, Up: Primitive Types

2.1.2 Real Number Types

There are several data types that represent fractional numbers, such as 3.14159 and 2.83. The exact sizes and ranges for the floating point data types can vary from system to system; these values are stored in macro definitions in the library header file float.h. In this section, we include the names of the macro definitions in place of their possible values:

All floating point data types are signed; trying to use unsigned float, for example, will cause a compile-time error.


Previous: Real Number Types, Up: Primitive Types

2.1.3 Complex Number Types

In an extension to standard C, the GNU C compiler provides support for complex number data types. You can declare complex character types, complex integer types, and complex floating point types using the keyword __complex__. We won't give you a complete list of all possibilities, since __complex__ can be used with any of these primitive data types, but here are some examples:

To extract the real part of a complex-valued expression, use the keyword __real__, followed by the expression. Likewise, use __imag__ to extract the imaginary part.

     __complex__ float a = 4 + 3i;
     
     float b = __real__ a;          /* b is now 4. */
     float c = __imag__ a;          /* c is now 3. */

This example creates a complex floating point variable a, and defines its real part as 4 and its imaginary part as 3. Then, the real part is assigned to the floating point variable b, and the imaginary part is assigned to the floating point variable c.


Next: , Previous: Primitive Types, Up: Data Types

2.2 Enumerations

An enumeration is a custom data type used for storing constant integer values and referring to them by names.


Next: , Previous: Enumerations, Up: Enumerations

2.2.1 Defining Enumerations

You define an enumeration using the enum keyword, followed by the name of the enumeration (this is optional), followed by a list of constant names (separated by commas and enclosed in braces), and ending with a semicolon.

     enum fruit {grape, cherry, lemon, kiwi};

That example defines an enumeration, fruit, which contains four constant integer values, grape, cherry, lemon, and kiwi, whose values are, by default, 0, 1, 2, and 3, respectively. You can also specify one or more of the values explicitly:

     enum more_fruit {banana = -17, apple, blueberry, mango};

That example defines banana to be -17, and the remaining values are incremented by 1—apple is -16, blueberry is -15, and mango is -14. Unless specified otherwise, an enumeration value is equal to one more than the previous value (and the first value defaults to 0).

You can also refer to an enumeration value defined earlier in the same enumeration:

     enum yet_more_fruit {kumquat, raspberry, peach,
                          plum = peach + 2};

In that example, kumquat is 0, raspberry is 1, peach is 2, and plum is 4.


Previous: Defining Enumerations, Up: Enumerations

2.2.2 Declaring Enumerations

You can declare variables of an enumeration type both when the enumeration is defined and afterward.

     enum fruit {banana, apple, blueberry, mango} my_fruit;

That example declares one variable of type enum fruit.

     enum fruit {banana, apple, blueberry, mango};
     
     enum fruit my_fruit;

That example also declares one variable of type enum fruit. (Of course, you couldn't declare it that way if you hadn't named the enumeration.)

Although such variables are considered to be of an enumeration type, you can assign them any value that you could assign to an int variable, including values from other enumerations. Furthermore, any variable that can be assigned an int value can be assigned a value from an enumeration.

However, you cannot change the values in an enumeration once it has been defined; they are constant values. For example, this won't work:

     enum fruit {banana, apple, blueberry, mango};
     
     banana = 15;  /* You can't do this! */


Next: , Previous: Enumerations, Up: Data Types

2.3 Unions

A union is a custom data type used for storing several variables in the same memory space. Although you can access any of those variables at any time, you should only read from one of them at a time—assigning a value to one of them overwrites the values in the others.


Next: , Previous: Unions, Up: Unions

2.3.1 Defining Unions

You define a union using the union keyword followed by the declarations of the union's members, enclosed in braces. You declare each member of a union just as you would normally declare a variable—using the data type followed by one or more variable names separated by commas, and ending with a semicolon. Then end the union definition with a semicolon after the closing brace.

You should also include a name for the union in between the union keyword and the opening brace. This is optional, but if you leave it out, you can't refer to that union data type later on.

Here is an example of defining a simple union for holding an integer value and a floating point value:

     union numbers
       {
         int i;
         float f;
       };

That defines a union named numbers, which contains two members, i and f, which are of type int and float, respectively.


Next: , Previous: Defining Unions, Up: Unions

2.3.2 Declaring Union Variables

You can declare variables of a union type when both you initially define the union and after the definition, provided you gave the union type a name.


Next: , Previous: Declaring Union Variables, Up: Declaring Union Variables
2.3.2.1 Declaring Union Variables at Definition

You can declare variables of a union type when you define the union type by putting the variable names after the closing brace of the union definition, but before the final semicolon. You can declare more than one such variable by separating the names with commas.

     union numbers
       {
         int i;
         float f;
       } first_number, second_number;

That example declares two variables of type union numbers, first_number and second_number.


Next: , Previous: Declaring Union Variables at Definition, Up: Declaring Union Variables
2.3.2.2 Declaring Union Variables After Definition

You can declare variables of a union type after you define the union by using the union keyword and the name you gave the union type, followed by one or more variable names separated by commas.

     union numbers
       {
         int i;
         float f;
       };
     
     union numbers first_number, second_number;

That example declares two variables of type union numbers, first_number and second_number.


Previous: Declaring Union Variables After Definition, Up: Declaring Union Variables
2.3.2.3 Initializing Union Members

You can initialize the first member of a union variable when you declare it:

     union numbers
       {
         int i;
         float f;
       };
     
     union numbers first_number = { 5 };

In that example, the i member of first_number gets the value 5. The f member is left alone.

Another way to initialize a union member is to specify the name of the member to initialize. This way, you can initialize whichever member you want to, not just the first one. There are two methods that you can use—either follow the member name with a colon, and then its value, like this:

     union numbers first_number = { f: 3.14159 };

or precede the member name with a period and assign a value with the assignment operator, like this:

     union numbers first_number = { .f = 3.14159 };

You can also initialize a union member when you declare the union variable during the definition:

     union numbers
       {
         int i;
         float f;
       } first_number = { 5 };


Next: , Previous: Declaring Union Variables, Up: Unions

2.3.3 Accessing Union Members

You can access the members of a union variable using the member access operator . . You put the name of the union variable on the left side of the operator, and the name of the member on the right side.

     union numbers
       {
         int i;
         float f;
       };
     
     union numbers first_number;
     
     first_number.i = 5;
     
     first_number.f = 3.9;

Notice in that example that giving a value to the f member overrides the value stored in the i member.


Previous: Accessing Union Members, Up: Unions

2.3.4 Size of Unions

This size of a union is equal to the size of its largest member. Consider the first union example from this section:

     union numbers
       {
         int i;
         float f;
       };

The size of the union data type is the same as sizeof (float), because the float type is larger than the int type. Since all of the members of a union occupy the same memory space, the union data type size doesn't need to be large enough to hold the sum of all their sizes; it just needs to be large enough to hold the largest member.


Next: , Previous: Unions, Up: Data Types

2.4 Structures

A structure is a programmer-defined data type made up of variables of other data types (possibly other structure types).


Next: , Previous: Structures, Up: Structures

2.4.1 Defining Structures

You define a structure using the struct keyword followed by the declarations of the structure's members, enclosed in braces. You declare each member of a structure just as you would normally declare a variable—using the data type followed by one or more variable names separated by commas, and ending with a semicolon. Then end the structure definition with a semicolon after the closing brace.

You should also include a name for the structure in between the struct keyword and the opening brace. This is optional, but if you leave it out, you can't refer to that structure data type later on.

Here is an example of defining a simple structure for holding the X and Y coordinates of a point:

     struct point
       {
         int x, y;
       };

That defines a structure named point, which contains two members, x and y, both of which are of type int.


Next: , Previous: Defining Structures, Up: Structures

2.4.2 Declaring Structure Variables

You can declare variables of a structure type when both you initially define the structure and after the definition, provided you gave the structure type a name.


Next: , Previous: Declaring Structure Variables, Up: Declaring Structure Variables
2.4.2.1 Declaring Structure Variables at Definition

You can declare variables of a structure type when you define the structure type by putting the variable names after the closing brace of the structure definition, but before the final semicolon. You can declare more than one such variable by separating the names with commas.

     struct point
       {
         int x, y;
       } first_point, second_point;

That example declares two variables of type struct point, first_point and second_point.


Next: , Previous: Declaring Structure Variables at Definition, Up: Declaring Structure Variables
2.4.2.2 Declaring Structure Variables After Definition

You can declare variables of a structure type after defining the structure by using the struct keyword and the name you gave the structure type, followed by one or more variable names separated by commas.

     struct point
       {
         int x, y;
       };
     
     struct point first_point, second_point;

That example declares two variables of type struct point, first_point and second_point.


Previous: Declaring Structure Variables After Definition, Up: Declaring Structure Variables
2.4.2.3 Initializing Structure Members

You can initialize the members of a structure type to have certain values when you declare structure variables. One way is to specify the values in a set of braces and separated by commas. Those values are assigned to the structure members in the same order that the members are declared in the structure in definition.

     struct point
       {
         int x, y;
       };
     
     struct point first_point = { 5, 10 };

In that example, the x member of first_point gets the value 5, and the y member gets the value 10.

Another way to initialize the members is to specify the name of the member to initialize. This way, you can initialize the members in any order you like, and even leave some of them uninitialized. There are two methods that you can use—either follow the member name with a colon, and then its value, like this:

     struct point first_point = { y: 10, x: 5 };

or precede the member name with a period and assign a value with the assignment operator, like this:

     struct point first_point = { .y = 10, .x = 5 };

You can also initialize the structure variable's members when you declare the variable during the structure definition:

     struct point
       {
         int x, y;
       } first_point = { 5, 10 };

You can also initialize less than all of a structure variable's members:

     struct point
       {
         int x, y;
       };
     
     struct point first_point = { 5 };

In that example, only one member, x, is initialized. y is left uninitialized. (This is because the members are initialized in order of declaration, and x was declared before y.)

Here is another example that initializes a structure's members which are structure variables themselves:

     struct point
       {
         int x, y;
       };
     
     struct rectangle
       {
         struct point top_left, bottom_right;
       };
     
     struct rectangle my_rectangle = { {0, 5}, {10, 0} };

That example defines the rectangle structure to consist of two point structure variables. Then it declares one variable of type struct rectangle and initializes its members. Since its members are structure variables, there is an extra set of braces surrounding the members that belong to the point structure variables. However, those extra braces are not necessary; they just make the code easier to read.


Next: , Previous: Declaring Structure Variables, Up: Structures

2.4.3 Accessing Structure Members

You can access the members of a structure variable using the member access operator . . You put the name of the structure variable on the left side of the operator, and the name of the member on the right side.

     struct point
       {
         int x, y;
       };
     
     struct point first_point;
     
     first_point.x = 0;
     first_point.y = 5;

You can also access the members of a structure variable which is itself a member of a structure variable.

     struct rectangle
       {
         struct point top_left, bottom_right;
       };
     
     struct rectangle my_rectangle;
     
     my_rectangle.top_left.x = 0;
     my_rectangle.top_left.y = 5;
     
     my_rectangle.bottom_right.x = 10;
     my_rectangle.bottom_right.y = 0;


Next: , Previous: Accessing Structure Members, Up: Structures

2.4.4 Bit Fields

You can create structures with integer members of nonstandard sizes, called bit fields. You do this by specifying an integer (int, char, long int, etc.) member as usual, and inserting a colon and the number of bits that the member should occupy in between the member's name and the semicolon.

     struct card
       {
         unsigned int suit : 2;
         unsigned int face_value : 4;
       };

That example defines a structure type with two bit fields, suit and face_value, which take up 2 bits and 4 bits, respectively. suit can hold values from 0 to 3, and face_value can hold values from 0 to 15. Notice that these bit fields were declared as unsigned int; had they been signed integers, then their ranges would have been from -2 to 1, and from -8 to 7, respectively.

More generally, the range of an unsigned bit field of N bits is from 0 to 2^N - 1, and the range of a signed bit field of N bits is from -(2^N) / 2 to ((2^N) / 2) - 1.


Previous: Bit Fields, Up: Structures

2.4.5 Size of Structures

The size of a structure type is equal to the sum of the size of all of its members, possibly plus some padding.


Next: , Previous: Structures, Up: Data Types

2.5 Arrays

An array is a data structure that lets you store zero or more elements consecutively in memory.


Next: , Previous: Arrays, Up: Arrays

2.5.1 Declaring Arrays

You declare an array by specifying the data type for its elements, its name, and the number of elements it can store. Here is an example that declares an array that can store ten integers:

     int my_array[10];

The number of elements can be as small as zero, but it cannot be negative. Zero-length arrays are useful as the last element of a structure which is really a header for a variable-length object:

     struct line
     {
       int length;
       char contents[0];
     };
     
     {
       struct line *this_line = (struct line *)
         malloc (sizeof (struct line) + this_length);
       this_line -> length = this_length;
     }

You can also declare an array size using a variable instead of a constant. For example, here is a function definition that declares an array using its parameter as the number of elements:

     int
     my_function (int number)
     {
       int my_array[number];
       ...;
     }


Next: , Previous: Declaring Arrays, Up: Arrays

2.5.2 Initializing Arrays

You can initialize the elements in an array when you declare it by listing the initializing values, separated by commas, in a set of braces. Here is an example:

     int my_array[5] = { 0, 1, 2, 3, 4 };

You don't have to initialize all of the array elements. For example, this code initializes only the first three elements:

     int my_array[5] = { 0, 1, 2 };

That leaves the last two elements uninitialized.

You can also initialize array elements out of order, by specifying which array indices to initialize. To do this, include the array index in brackets, and optionally the assignment operator, before the value. (The first element in an array is at position 0, not 1.) Here is an example:

     int my_array[5] = { [2] 5, [4] 9 };

Or, using the assignment operator:

     int my_array[5] = { [2] = 5, [4] = 9 };

Both of those examples are equivalent to:

     int my_array[5] = { 0, 0, 5, 0, 9 };

You can also initialize a range of elements to the same value, by specifying the first and last indices, in the form [first] ... [last] . Here is an example:

     int new_array[100] = { [0 ... 9] = 1, [10 ... 98] = 2, 3 };

That initializes elements 0 through 9 to 1, elements 10 through 98 to 2, and element 99 to 3. (You also could explicitly write [99] = 3.) Also, notice that you must have spaces on both sides of the ....

If you initialize every element of an array, then you do not have to specify its size; its size is determined by the number of elements you initialize. Here is an example:

     int my_array[] = { 0, 1, 2, 3, 4 };

Although this does not explicitly state that the array has five elements using my_array[5], it initializes five elements, so that is how many it has.

Alternately, if you specify which elements to initialize, then the size of the array is equal to the highest element number initialized, plus one. For example:

     int my_array[] = { 0, 1, 2, [99] = 99 };

In that example, only four elements are initialized, but the last one initialized is element number 99, so there are 100 elements. (In GNU C, you start counting array elements with zero, not one.)


Next: , Previous: Initializing Arrays, Up: Arrays

2.5.3 Accessing Array Elements

You can access the elements of an array by specifying the array name, followed by the element index, enclosed in brackets. In C, the array elements are numbered starting with zero, not one. Here is an example:

     my_array[0] = 5;

That assigns the value 5 to the first element in the array, at position zero. You can treat individual array elements like variables of whatever data type the array is made up of. For example, if you have an array made of a structure data type, you can access the structure elements like this:

     struct point
     {
       int x, y;
     };
     
     struct point point_array[2] = { {4, 5}, {8, 9} };
     
     point_array[0].x = 3;


Next: , Previous: Accessing Array Elements, Up: Arrays

2.5.4 Multidimensional Arrays

You can make multidimensional arrays, or “arrays of arrays”. You do this by adding an extra set of brackets and array lengths for every additional dimension you want your array to have. For example, here is a declaration for a two-dimensional array that holds five elements in both dimensions:

     int two_dimensions[5][5];


Next: , Previous: Multidimensional Arrays, Up: Arrays

2.5.5 Arrays as Strings

You can use an array of characters to hold a string (see String Constants). The array may be built of either signed or unsigned characters.

When you declare the array, you can specify the number of elements it will have. That number will be the maximum number of characters that should be in the string, including the null character used to end the string. If you choose this option, then you do not have to initialize the array when you declare it. Alternately, you can choose not to explicitly state the number of elements the array will have. In this case, you must initialize the array, and then its size will be exactly large enough to hold whatever string you used to initialize it.

There are two different ways to initialize the array. You can specify of comma-delimited list of characters enclosed in braces, or you can specify a string literal enclosed in double quotation marks.

Here are some examples:

     char blue[26];  // This array can hold 26 characters, including
                     // the null character.
     char yellow[26] = {'y', 'e', 'l', 'l', 'o', 'w'};
     
     char orange[26] = "orange";
     
     char gray[] = {'g', 'r', 'a', 'y'};
     
     char salmon[] = "salmon";

In all of those cases, the null character \0 is automatically be appended to the end of each string, even though it was not explicitly included.

Both yellow and orange can hold 26 characters; in the above example, only seven were used. So you could still change what characters are in them, using up to 26 characters. However, gray holds only five characters, and salmon holds only seven. Since no array size was explicitly stated, the size is determined by the lengths of the string literals used to initialize them.

Also, note that, after initialization, you cannot assign a new string literal to an array using the assignment operator. For example, this will not work:

     char lemon[26] = "custard";
     
     lemon = "steak sauce";

However, there are functions in the GNU C library that perform operations (including copy) on string arrays.

It is possible for you to explicitly state the number of elements in the array, and then initialize it using a string that has more characters than there are elements in the array. This is not a good thing. The larger string will not override the previously specified size of the array, and you will get a compile-time warning. Since the original array size remains, any part of the string that exceeds that original size is being put into a memory location that was not allocated for it.

This same problem occurs regardless of if you initialize the string using a comma-delimited sequence of characters or a string literal.


Next: , Previous: Arrays as Strings, Up: Arrays

2.5.6 Arrays of Unions

You can create an array of a union type just like you can an array of a primitive data type.

     union numbers
       {
         int i;
         float f;
       };
     
     union numbers number_array [3];

That example creates a 3-element array of union numbers variables called number_array. You can also initialize the first members of the elements of a number array:

     struct point point_array [3] = { {3}, {4}, {5} };

The additional inner grouping braces are optional.

After initialization, you can still access the union members in the array using the member access operator. You put the array name and element number (enclosed in brackets) to the left of the operator, and the member name to the right.

     union numbers number_array [3];
     
     number_array[0].i = 2;


Previous: Arrays of Unions, Up: Arrays

2.5.7 Arrays of Structures

You can create an array of a structure type just like you can an array of a primitive data type.

     struct point
       {
         int x, y;
       };
     
     struct point point_array [3];

That example creates a 3-element array of struct point variables called point_array. You can also initialize the elements of a structure array:

     struct point point_array [3] = { {2, 3}, {4, 5}, {6, 7} };

As with initializing structures which contain structure members, the additional inner grouping braces are optional. But, if you use the additional braces, then you can partially initialize some of the structures in the array, and fully initialize others:

     struct point point_array [3] = { {2}, {4, 5}, {6, 7} };

In that example, the first element of the array has only its x member initialized. Because of the grouping braces, the value 4 is assigned to the x member of the second array element, not to the y member of the first element, as would be the case without the grouping braces.

After initialization, you can still access the structure members in the array using the member access operator. You put the array name and element number (enclosed in brackets) to the left of the operator, and the member name to the right.

     struct point point_array [3];
     
     point_array[0].x = 2;
     point_array[0].y = 3;


Next: , Previous: Arrays, Up: Data Types

2.6 Pointers

Pointers hold memory addresses of other constants or variables. For any data type, including both primitive types and custom types, you can create a pointer that holds the memory address of an instance of that type.


Next: , Previous: Pointers, Up: Pointers

2.6.1 Declaring Pointers

You declare a pointer by specifying a name for it and a data type. The data type indicates of what type of variable the pointer will hold memory addresses.

To declare a pointer, include the indirection operator (see The Indirection Operator) in between the data type and the identifier. Here is the general form of a pointer declaration:

     data-type * name;

More commonly, programmers put the operator either directly next to name, or directly next data-type, like this:

     data-type *name;
     data-type* name;

Any of these three is fine, and they all work the same way. Here is an example of declaring a pointer to hold the address of an int variable:

     int *ip;

Be careful, though: when declaring multiple pointers in the same statement, you must explicitly declare each as a pointer, using the indirection operator:

     int *bob, *emily;  // Two pointers.
     int *rob, laura;   // A pointer and an integer variable.


Next: , Previous: Declaring Pointers, Up: Pointers

2.6.2 Initializing Pointers

You can initialize a pointer when you first declare it by specifying a variable address to store in it. For example, the following code declares an int variable i, and a pointer which is initialized with the address of i:

     int i;
     int *ip = &i;

Note the use of the address operator (see The Address Operator), used to get the memory address of a variable. Be careful, though: after you declare a pointer, you do not use the indirection operator with the pointer's name when assigning it a new address to point to. On the contrary, that would change the value of the variable that the points to, not the value of the pointer itself. For example:

     int i, j;
     int *ip = &i;    // ip now holds the address of i.
     
     ip = &j;         // ip now holds the address of j.
     
     *ip = &i;        // j now holds the address of i.


Next: , Previous: Initializing Pointers, Up: Pointers

2.6.3 Pointers to Unions

You can create a pointer to a union type just like you can a pointer to a primitive data type.

     union numbers
       {
         int i;
         float f;
       };
     
     union numbers first_number = {4};
     
     union numbers *number_ptr = &first_number;

That example creates a new union type, union numbers, and declares (and initializes the first member of) a variable of that type named first_number. Finally, it declares a pointer to the type union numbers, and gives it the address of first_number.

You can access the members of a union variable through a pointer, but you can't use the regular member access operator anymore. Instead, you have to use the indirect member access operator -> . Continuing with the previous example, the following example will change the value of the first member of first_number:

     number_ptr -> i = 450;

Now the i member in first_number is 450.


Previous: Pointers to Unions, Up: Pointers

2.6.4 Pointers to Structures

You can create a pointer to a structure type just like you can a pointer to a primitive data type.

     struct fish
       {
         float length, weight;
       };
     
     struct fish salmon = {4.3, 5.8};
     
     struct fish *fish_ptr = &salmon;

That example creates a new structure type, struct fish, and declares (and initializes) a variable of that type named salmon. Finally, it declares a pointer to the type struct fish, and gives it the address of salmon.

You can access the members of a structure variable through a pointer, but you can't use the regular member access operator anymore. Instead, you have to use the indirect member access operator -> . Continuing with the previous example, the following example will change the values of the members of salmon:

     fish_ptr -> length = 5.1;
     fish_ptr -> weight = 6.2;

Now the length and width members in salmon are 5.1 and 6.2, respectively.


Next: , Previous: Pointers, Up: Data Types

2.7 Incomplete Types

You can define structures, unions, and enumerations without listing their members (or values, in the case of enumerations). Doing so results in an incomplete type. You can't declare variables of incomplete types, but you can work with pointers to those types.

     struct point;

At some time later in your program you will want to complete the type. You do this by defining it as you usually would:

     struct point
       {
         int x, y;
       };


Previous: Incomplete Types, Up: Data Types

2.8 Storage and Access Modifiers


Next: , Previous: Data Types, Up: Top

3 Expressions and Operators


Next: , Previous: Expressions and Operators, Up: Expressions and Operators

3.1 Expressions

An expression consists of at least one operand and zero or more operators. The operands may be any value, including constants, variables, and function calls that return values. Here are some examples:

     47
     2 + 2
     function()

The last of those expressions, function(), is only an expression if function() has a return type other than void.

You can use parentheses to group subexpressions.

     ( 2 * ( ( 3 + 10 ) - ( 2 * 6 ) ) )

Innermost expressions are evaluated first. In the above example, 3 + 10 and 2 * 6 evaluate to 13 and 12, respectively. Then 12 is subtracted from 13, resulting in 1. Finally, 1 is multiplied by 2, resulting in 2. The outermost parentheses are completely optional.

An operator specifies an operation to be performed on its operand(s). In GNU C, operators may have one, two, or three operands, depending on the operator.


Next: , Previous: Expressions, Up: Expressions and Operators

3.2 Unary Operators

Unary operators perform an operation on a single operand.


Next: , Previous: Unary Operators, Up: Unary Operators

3.2.1 The Increment Operator

The increment operator ++ adds 1 to its operand. The operand must be a either a variable of one of the primitive data types, a pointer, or an enumeration variable. Here are some examples:

     int x = 5;
     char y = 'B';
     float z = 5.2;
     int *p = &x;
     
     x++;   /* x is now 6. */
     y++;   /* y is now `C'. */
     z++;   /* z is now 6.2. */
     p++;   /* p is now &x + sizeof(int). */

You can use the increment operator either before or after the operand. A prefix increment adds 1 before the operand is evaluated. A postfix increment adds 1 after the operand is evaluated. In the previous examples, that wouldn't have made any difference. However, there are cases where it does make a difference:

     int x = 5;
     
     printf ("%d \n", x++);    /* Print x and then increment it. */
     
     /* x is now equal to 6. */
     
     printf ("%d \n", ++x);    /* Increment x and then print it. */

The output of the above example is:

     5
     7


Next: , Previous: The Increment Operator, Up: Unary Operators

3.2.2 The Decrement Operator

The decrement operator -- subtracts 1 from its operand. The operand must be a either a variable of one of the primitive data types, a pointer, or an enumeration variable. Here are some examples:

     int x = 5;
     char y = 'B';
     float z = 5.2;
     int *p = &x;
     
     x--;   /* x is now 4. */
     y--;   /* y is now `A'. */
     z--;   /* z is now 4.2. */
     p--;   /* p is now &x - sizeof(int). */

You can use the decrement operator either before or after the operand. A prefix decrement subtracts 1 before the operand is evaluated. A postfix increment subtracts 1 after the operand is evaluated. In the previous examples, that wouldn't have made any difference. However, there are cases where it does make a difference:

     int x = 5;
     
     printf ("%d \n", x--);   /* Print x and then decrement it. */
     
     /* x is now 4 */
     
     printf ("%d \n", --x);   /* Decrement x and then print it. */

The output of the above example is:

     5
     3


Next: , Previous: The Decrement Operator, Up: Unary Operators

3.2.3 The Positive Operator

You can use the positive operator + on numeric values to indicate that their value is positive. By default, values are positive unless explicitly stated to be negative, so there is no need to use this operator as far as the compiler is concerned. However, you can use it to visually enforce the fact that a value is positive. Here are some examples:

     int x = +5;
     float y = +3.14159;


Next: , Previous: The Positive Operator, Up: Unary Operators

3.2.4 The Negative Operator

You can use the negative operator - on numeric variables and constants to indicate that their value is negative. Here are some examples:

     int x = -5;
     float y = -3.14159;

If the operand you use with the negative operator is of an unsigned data type, then the result is not negative, but rather it is the maximum value of the unsigned data type, minus the value of the operand.


Next: , Previous: The Negative Operator, Up: Unary Operators

3.2.5 The Logical Negation Operator

You can use the logical negation operator ! to get the logical opposite of its operand. If its operand is 0 (or null, if the operand is a pointer), then the result of the logical negation operator is 1. If its operand is anything other than 0 (or null), then the result of the logical negation operator is 0. In any case, the result is an integer value. Here are some examples:

     int x = !5;   /* x is 0. */
     
     if (!x)
       printf ("x is 0");


Next: , Previous: The Logical Negation Operator, Up: Unary Operators

3.2.6 The Bitwise Complement Operator

You can use the bitwise complement operator ~ to find the one's complement of its operand. The operand must be an integer or character type. The bitwise complement operator examines its operand's bits, and changes all 0 bits to 1 and all 1 bits to 0. Here is an example:

     unsigned int x = 500;
     unsigned int y;
     
     y = ~x;

Using signed data types with the bitwise complement operator may cause portability problems. You should use unsigned data types for maximum portability.


Next: , Previous: The Bitwise Complement Operator, Up: Unary Operators

3.2.7 The Address Operator

You can use the address operator & to obtain the memory address of its operand. You can use this operator both with variables of any data type (including arrays and structures) and with functions, but you can't use it with literal values. You should only store the result of the address operator in pointer variables.

     int x = 5;
     int *ptr;
     
     ptr = &x;


Next: , Previous: The Address Operator, Up: Unary Operators

3.2.8 The Indirection Operator

You can use the indirection operator * to obtain the value stored at the address specified by its operand. This is also known as dereferencing its operand. Its operand must be a pointer.

     int x = 5;
     int y;
     int *ptr;
     
     ptr = &x;    /* ptr now holds the address of x. */
     
     y = *ptr;    /* y gets the value stored at the address
                     stored in ptr. */

Be sure to only use the indirection operator with pointers that have been initialized. Otherwise, the value stored in those pointers probably won't be anything you want to use.


Next: , Previous: The Indirection Operator, Up: Unary Operators

3.2.9 The Complex Conjugation Operator

You can use the complex conjugation operator ~ to perform complex conjugation on its operand — that is, it reverses the sign of its imaginary component. The operand must be an expression of a complex number type. Here is an example:

     __complex__ int x = 5 + 17i;
     
     printf ("%d  \n", (x * ~x));

Since an imaginary number (a + bi) multiplied by its conjugate is equal to a^2 + b^2, the above printf statement will print 314, which is equal to 25 + 289.


Next: , Previous: The Complex Conjugation Operator, Up: Unary Operators

3.2.10 The sizeof Operator

You can use the sizeof operator to obtain the size (in bytes) of the data type of its operand. The operand may be an actual type specifier (such as int or float), as well as any valid expression. You must enclose the operand in parentheses after the operator. Here are some examples:

     printf ("%d \n", sizeof (int) );
     printf ("%d \n", sizeof (float) );
     printf ("%d \n", sizeof (5) );
     printf ("%d \n", sizeof (5.1) );

The result of the sizeof operator is of a type called size_t, which is defined in the header file stddef.h. size_t is an unsigned integer type, perhaps identical to unsigned int or unsigned long int. This can vary from system to system.


Next: , Previous: The sizeof Operator, Up: Unary Operators

3.2.11 Type Casts

You can use a type cast to explicitly declare the data type of an expression. A type cast consists of a type specifier enclosed in parentheses, followed by an expression. To ensure proper casting, you should also enclose the expression that follows the type specifier in parentheses. Here is an example:

     float x;
     int y = 7;
     int z = 3;
     
     x = (float)(y / z);

In that example, since y and z are both integers, integer division is performed, and even though x is a floating-point variable, it receives the value 2. By explicitly casting the result of the division to float, the floating-point value 2.333... can be retained and assigned to x.


Next: , Previous: Type Casts, Up: Unary Operators

3.2.12 Array Subscripts

You can access array elements by specifying the name of the array, and the array subscript (or index, or element number) enclosed in brackets. Here is an example, using an integer array called my_array:

     my_array[0] = 5;


Previous: Array Subscripts, Up: Unary Operators

3.2.13 Function Calls as Expressions

A function call is an expression if the function returns a value, regardless of if the returned value is used or not.

     int function( void );
     ...
     a = 10 + function();


Next: , Previous: Unary Operators, Up: Expressions and Operators

3.3 Binary Operators


Next: , Previous: Binary Operators, Up: Binary Operators

3.3.1 The Addition Operator

You use the addition operator + to add two operands. You put the operands on either side of the operator, and it does not matter which operand is goes on which side: 3 + 5 and 5 + 3 both result in 8. The operands must be either expressions of a primitive data type or pointers.

     x = 5 + 3;
     y = 10 + 37;
     z = 1 + 2 + 3 + 4 + 5;

When you use more than one addition operator (and more than two operands), such as in the last example, the expression is evaluated from left to right.


Next: , Previous: The Addition Operator, Up: Binary Operators

3.3.2 The Subtraction Operator

You use the subtraction operator - to subtract its second operand from its first operand. You put the operands on either side of the operator, and it does matter which operand goes on which side: 3 - 5 and 5 - 3 do not both have the same result. The operands must be either expressions of a primitive data type or pointers.

     x = 5 - 3;
     y = 57 - 10;
     z = 5 - 4 - 3 - 2 - 1;

When you use more than one subtraction operator (and more than two operands), such as in the last example, the expression is evaluated from left to right.


Next: , Previous: The Subtraction Operator, Up: Binary Operators

3.3.3 The Multiplication Operator

You use the multiplication operator * to multiply two operands together. You put the operands on either side of the operator, and it does not matter which operand goes on which side: 3 * 5 and 5 * 3 both result in 15. The operands must be expressions of a primitive data type.

     x = 5 * 3;
     y = 47 * 1;
     z = 1 * 2 * 3 * 4 * 5;

When you use more than one multiplication operator (and more than two operands), such as in the last example, the expression is evaluated from left to right.


Next: , Previous: The Multiplication Operator, Up: Binary Operators

3.3.4 The Division Operator

You use the division operator / to divide its first operand by its second operand. You put the operands on either side of the operator, and it does matter which operand goes on which side: 3 / 5 and 5 / 3 do not both have the same result. The operands must be expressions of a primitive data type.

     x = 5 / 3;
     y = 940 / 20;
     z = 100 / 2 / 2;

When you use more than one division operator (and more than two operands), such as in the last example, the expression is evaluated from left to right.


Next: , Previous: The Division Operator, Up: Binary Operators

3.3.5 The Modulus Operator

You use the modulus operator % to obtain the remainder produced by dividing its two operands. You put the operands on either side of the operator, and it does matter which operand goes on which side: 3 % 5 and 5 \% 3 do not both have the same result. The operands must be expressions of a primitive data type.

     x = 5 % 3;
     y = 74 % 47;
     z = 47 % 32 % 21;

When you use more than one modulus operator (and more than two operands), like in the last example, the expression is evaluated from left to right.

A common application of the modulus operator is to determine if one number is divisible by another number. If it is divisible, then the remainder is zero. Here is an example of that:

     int counter;
     
     for( counter = 0; counter <= 100; counter++ )
       {
         if( counter % 5 == 0 )
           printf("%d\n", counter);
       }

That prints all of the integers from 0 to 100 that are divisible by 5.


Next: , Previous: The Modulus Operator, Up: Binary Operators

3.3.6 The Shift Operators

You use the left-shift operator << to shift its first operand's bits to the left. You specify the number of bit-places shifted with the second operand. If there is a 1 bit in the leftmost bit position, it will be discarded. New bits that are added to the rightmost bit position will all be 0.

     
     x = 47;    /* 47 is 00101111 in binary. */
     
     x << 1;    /* 00101111 << 1 is 01011110. */

You use the right-shift operator >> to shift its first operand's bits to the right. You specify the number of bit-places shifted with the second operand. If there is a 1 bit in the rightmost bit position, it will be discarded. New bits that are added to the leftmost bit position may be either 0 or 1. If the first operand is unsigned, then the added bits will be 0. If it is signed, the added bits will be either 0 or whatever value was previously in the leftmost bit position.

     x = 47;   /* 47 is 00101111 in binary. */
     
     x >> 1;   /* 00101111 >> 1 is 00010111. */


Next: , Previous: The Shift Operators, Up: Binary Operators

3.3.7 The Bitwise AND Operator

The bitwise AND operator & examines each bit in its two operands, and when two corresponding bits are both 1, the resulting bit is 1. In every other case the result is 0. Here is an example of how this operator works, using binary numbers:

     11001001 & 10011011 = 10001001

If you look closely at that, you'll see that when a bit is 1 in both operands, the corresponding bit in the result is set to 1. Otherwise it is set to 0. Here is another example, this time in C:

     char x = 149, y = 34, z;
     
     z = x & y;


Next: , Previous: The Bitwise AND Operator, Up: Binary Operators

3.3.8 The Bitwise Inclusive OR Operator

The bitwise inclusive OR operator | examines each bit in its two operands, and when two corresponding bits are both 0, the resulting bit is 0. In every other case the resulting bit is 1. Here is an example of how this operator works, using binary numbers:

     11001001 | 10011011 = 11011011

Here is another example, this time in C:

     char x = 149, y = 34, z;
     
     z = x | y;


Next: , Previous: The Bitwise Inclusive OR Operator, Up: Binary Operators

3.3.9 The Bitwise Exclusive OR Operator

The bitwise exclusive OR operator ^ (also known as XOR) examines each bit in its two operands, and when two corresponding bits are different, the resulting bit is 1. When they are the same, the resulting bit is 0. Here is an example of how this operator works, using binary numbers:

     11001001 | 10011011 = 01011001

Here is another example, this time in C.

     char x = 149, y = 34, z;
     
     z = x ^ y;


Next: , Previous: The Bitwise Exclusive OR Operator, Up: Binary Operators

3.3.10 The Comparison Operators

You use the comparison operators to determine how two operands relate to each other—are they equal to each other, is one larger than the other, is one smaller than the other, and so on. When you use any of the comparison operators, the result is either 1 or 0, meaning true or false, respectively.

In the example program fragments, the variables x and y stand for any two expressions of primitive types, or pointers.


Next: , Previous: The Comparison Operators, Up: The Comparison Operators
3.3.10.1 The Equal-to Operator

Use the equal-to operator == to test two operands for equality. It evaluates to 1 if the two operands are equal, and 0 if the two operands are not equal.

     if (x == y)
       printf ("x is equal to y");
     else
       printf ("x is not equal to y");


Next: , Previous: The Equal-to Operator, Up: The Comparison Operators
3.3.10.2 The Not-Equal-to Operator

Use the not-equal-to operator != to test two operands for inequality. If the two operands are not equal, the result is 1. Otherwise, if the two operands are equal, the result is 0.

     if (x != y)
       printf ("x is not equal to y");
     else
       printf ("x is equal to y");


Next: , Previous: The Not-Equal-to Operator, Up: The Comparison Operators
3.3.10.3 The Less-Than Operator

Use the less-than operator < to determine if the first operand is less than the second operand. If it is, the result is 1. Otherwise, the result is 0.

     if (x < y)
       printf ("x is less than y");
     else
       printf ("x is not less than y");


Next: , Previous: The Less-Than Operator, Up: The Comparison Operators
3.3.10.4 The Less-Than-or-Equal-to Operator

Use the less-than-or-equal-to operator <= to determine if the first operand is less than or equal to the second operand. If it is, the result is 1. Otherwise, the result is 0.

     if (x <= y)
       printf ("x is less than or equal to y");
     else
       printf ("x is not less than or equal to y");


Next: , Previous: The Less-Than-or-Equal-to Operator, Up: The Comparison Operators
3.3.10.5 The Greater-Than Operator

Use the greater-than operator > to determine if the first operand is greater than the second operand. If it is, the result is 1. Otherwise, the result is 0.

     if (x > y)
       printf ("x is greater than y");
     else
       printf ("x is not greater than y");


Previous: The Greater-Than Operator, Up: The Comparison Operators
3.3.10.6 The Greater-Than-or-Equal-to Operator

Use the greater-than-or-equal-to operator >= to determine if the first operand is greater than or equal to the second operand. If it is, the result is 1. Otherwise, the result is 0.

     if (x >= y)
       printf ("x is greater than or equal to y");
     else
       printf ("x is not greater than or equal to y");


Next: , Previous: The Comparison Operators, Up: Binary Operators

3.3.11 Logical Operators

You can use the logical operators to test the truth value of two operands. The operands can be expressions of a primitive type, or pointers.

Note that while the comparison operators return the value 1 for a true expression, any nonzero expression is considered true in C.


Next: , Previous: Logical Operators, Up: Logical Operators
3.3.11.1 The Logical AND Operator

Use the logical AND operator && to test if two expressions are both true. If the first one is not true, then the second one is not evaluated.

     if ((x == 5) && (y == 10))
       printf ("x is 5 and y is 10");

You can also build an expression using more than one AND operator, and more than two operands, like this:

     if ((x == 5) && (y == 10) && (z == 15))
       printf ("x is 5 and y is 10 and z is 15");


Previous: The Logical AND Operator, Up: Logical Operators
3.3.11.2 The Logical OR Operator

Use the logical OR operator || to test if at least one of two expressions is true. If the first expression is true, then the second expression is not evaluated.

     if ((x == 5) || (y == 10))
        printf ("x is 5 or y is 10");

You can also build an expression using more than one OR operator, and more than two operands, like this:

     if ((x == 5) || (y == 10) || (z == 15))
         printf ("x is 5 or y is 10 or z is 15");


Next: , Previous: Logical Operators, Up: Binary Operators

3.3.12 Assignment Operators

You use the assignment operators to give values to variables. Regardless of which assignment operator is being used, the first operand — the operand to which a value is being assigned, also known as the “lvalue” — cannot be a literal value or any other constant value. Except as noted, the operands must be of a primitive data type, or a pointer.


Next: , Previous: Assignment Operators, Up: Assignment Operators
3.3.12.1 The Assignment Operator

Use the standard assignment operator = to assign the value of its right operand to its left operand. Unlike the other assignment operators, you can use this operator with variables of a structure type, in addition to primitive types and pointers.

     x = 10;
     y = 45 + 2;
     z = (2 * (3 + function () ));


Next: , Previous: The Assignment Operator, Up: Assignment Operators
3.3.12.2 The Compound Assignment Operators

You use the compound assignment operators to perform an operation on both the left and right operands, and then assign the resulting expression to the left operand. Here is a list of the compound assignment operators, and a brief description of what they do:

Here is an example of using one of the compound assignment operators:

     x += y;

That produces the same result as:

     x = x + y;


Previous: The Compound Assignment Operators, Up: Assignment Operators
3.3.12.3 Generalized Lvalues

Compound expressions, conditional expressions and casts are allowed as lvalues provided their operands are lvalues. This means that you can take their addresses or store values into them.

For example, you can assign a value to a compound expression, provided the last expression in the sequence is an lvalue. These two expressions are equivalent:

     (a, b) += 5
     a, (b += 5)

Similarly, you can take the address of a compound expression. So, these two expressions are equivalent:

     &(a, b)
     a, &b

A conditional expression is a valid lvalue if its type is not void and if both the second and third operands are valid lvalues. For example, these two expressions are equivalent:

     (a ? b : c) = 5
     (a ? b = 5 : (c = 5))

A type cast is a valid lvalue if its operand is an lvalue. A simple assignment whose left-hand side is a cast works by converting the right-hand side first to the specified type, then to the type of the inner left-hand side expression. After this is stored, the value is converted back to the specified type to become the value of the assignment. Thus, if a has type char *, the following two expressions are equivalent:

     (int)a = 5
     (int)(a = (char *)(int)5)

An assignment-with-arithmetic operation such as += applied to a cast performs the arithmetic using the type resulting from the cast, and then continues as in the previous case. Therefore, these two expressions are equivalent:

     (int)a += 5
     (int)(a = (char *)(int) ((int)a + 5))

You cannot take the address of an lvalue cast, because the use of its address would not work out coherently. Suppose that &(int)f were permitted, where f has type float. Then the following statement would try to store an integer bit-pattern where a floating point number belongs:

     *&(int)f = 1;

This is quite different from what (int)f = 1 would do—that would convert 1 to floating point and store it. Rather than cause this inconsistency, we think it is better to prohibit use of & on a cast.

If you really do want an int * pointer with the address of f, you can simply write (int *)&f.


Next: , Previous: Assignment Operators, Up: Binary Operators

3.3.13 The Comma Operator

You use the comma operator , to separate two expressions. These expressions don't have to be related at all, but often the first expression produces a value that is used by the second expression.

     int x = 5, y = 10;
     
     x++, y = x * x;

More commonly, the comma operator is used in for statements, like this:

     /* Using the comma operator in a for statement. */
     
     for (x = 1, y = 10;  x <=10 && y >=1;  x++, y--)
       {
         ...
       }

A comma is also used to separate function parameters; however, this is not the comma operator in action. In fact, if the comma operator is used as we have discussed here in a function call (without enclosing it in an additional set of parentheses), then the compiler will interpret that as calling the function with an extra parameter.

     function (x,  y=47, y,  z);

Even though what may be intended by such a function call is to call the function with the parameters x, y, and z, with y set to 47, what will happen is that the function will be called with the parameters x, y=47, y, and z. So if you want to include expressions that use the comma operator in a function call, surround the comma operator expression with parentheses.

     function (x,  (y=47, y),  z);

That will call function with the parameters x, y, and z, with y set to 47.


Previous: The Comma Operator, Up: Binary Operators

3.3.14 Member Access Operators

You can use the member access operator . to access the members of a structure or union variable. You put the name of the structure variable on the left side of the operator, and the name of the member on the right side.

     struct point
     {
       int x, y;
     };
     
     struct point first_point;
     
     first_point.x = 0;
     first_point.y = 5;

You can also access the members of a structure or union variable via a pointer by using the indirect member access operator ->.

     struct fish
       {
         int length, weight;
       };
     
     struct fish salmon;
     
     struct fish *fish_pointer = &salmon;
     
     fish_pointer -> length = 3;
     fish_pointer -> weight = 9;

See Pointers.


Next: , Previous: Binary Operators, Up: Expressions and Operators

3.4 The Ternary Operator

GNU C has only one ternary operator — the conditional operator ? :.

You use the conditional operator to cause the entire conditional expression to evaluate to either its second or its third operand, based on the truth value of its first operand.

Put the first operand is before the question mark; this operand may be any expression. If it evaluates to true (nonzero), then the second operand (which is also an expression), which is placed in between the question mark and the colon, is evaluated, and becomes the value of the conditional expression. Otherwise, the third operand (also an expression), which is placed after the colon, is evaluated, and becomes the value of the conditional expression. Here is an example

     a = (x == 5) ? y : z;

In that example, if x equals 5, then a will receive the value y. Otherwise, a will receive the value z. Really, this is a shorthand method for writing a simple if...else statement. The previous example will accomplish the same task as the following example:

     if( x != 0)
         a = y;
     else
         a = z;

If the first operand of the conditional operator is true, then the third operand is never evaluated. Similarly, if the first operand is false, then the second operand is never evaluated. The first operand is always evaluated.

You can also leave out the second operand — this is similar to using the first operand as both the first operand and the second operand. For example, the expression

     x ? : y

has the same value as

     x ? x : y

In simple examples like that one, there is no point to leaving out the second operand. However, if the first operand had a side effect, such as incrementing a variable, then you might not want that side effect to happen twice, so you shouldn't include it as both the first and second operands.


Next: , Previous: The Ternary Operator, Up: Expressions and Operators

3.5 Statements and Declarations in Expressions

A compound statement enclosed in parentheses may appear as an expression in GNU C. This allows you to use loops, switches, and local variables within an expression.

Recall that a compound statement (also known as a block) is a sequence of statements surrounded by braces; in this construct, parentheses go around the braces. Here is an example:

     ({ int y = function (); int z;
        if (y > 0) z = y;
        else z = - y;
        z; })

That is a valid (though slightly more complex than necessary) expression for the absolute value of function ().

The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct. (If you use some other kind of statement last within the braces, the construct has type void, and thus effectively no value.)

This feature is especially useful in making macro definitions “safe” (so that they evaluate each operand exactly once). For example, the “maximum” function is commonly defined as a macro in standard C as follows:

     #define max(a,b) ((a) > (b) ? (a) : (b))

But this definition computes either a or b twice, with bad results if the operand has side effects. In GNU C, if you know the type of the operands (here let's assume int), you can define the macro safely as follows:

     #define maxint(a,b) \
       ({int _a = (a), _b = (b); _a > _b ? _a : _b; })

Embedded statements are not allowed in constant expressions, such as the value of an enumeration constant, the width of a bit field, or the initial value of a static variable.

If you don't know the type of the operand, you can still do this, but you must use typeof expressions or type naming.


Previous: Statements and Declarations in Expressions, Up: Expressions and Operators

3.6 Order of Evaluation

When an expression consists of subexpressions, such as a + b * f(), the subexpressions are not all evaluated at once, nor are they necessarily evaluated left to right as they appear in the expression. In the preceding example, for instance, the function call f() will be evaluated first, the result of which will be multiplied by b, the result of which will be added to a. That is not intuitive simply by looking at the expression, but there is a definite order in which subexpressions are evaluated.

The following is a list of types of expressions, presented in the same order that they are evaluated. The expressions that are evaluated first are said to have the highest precedence, and those that are evaluated last the low precedence. Some types of expressions have the same precedence. If two or more subexpressions have the same precedence, then they are usually evaluated left to right. If they are not evaluated left to right, then that is explicitly stated in the list.

  1. Function calls, array subscripting, and membership access operator expressions.
  2. Logical negation, bitwise complement, increment, decrement, unary positive, unary negative, indirection operator, address operator, type casting, and sizeof expressions. When used as subexpressions, these are evaluated right to left.
  3. Multiplication, division, and modular division expressions.
  4. Addition and subtraction expressions.
  5. Bitwise shifting expressions.
  6. Greater-than, less-than, greater-than-or-equal-to, and less-than-or-equal-to expressions.
  7. Equal-to and not-equal-to expressions.
  8. Bitwise AND expressions.
  9. Bitwise exclusive OR expressions.
  10. Bitwise inclusive OR expressions.
  11. Logical AND expressions.
  12. Logical OR expressions.
  13. Conditional operator expressions (using ?:). When used as subexpressions, these are evaluated right to left.
  14. All assignment expressions, including compound assignment. When used as subexpressions, these are evaluated right to left.
  15. Comma operator expressions.


Next: , Previous: Expressions and Operators, Up: Top

4 Statements

In general, statements cause action in a computer program, such as storing a value into a variable or cycling through loops.


Next: , Previous: Statements, Up: Statements

4.1 Expression Statements

You can turn any expression into a statement by adding a semicolon to the end of the expression. Here are some examples:

     5;
     2 + 2;
     10 >= 9;

In each of those, all that happens is that each expression is evaluated. However, they are useless because they do not store a value anywhere, nor do they actually do anything, other than the evaluation itself. The compiler is free to ignore such statements.

Expression statements are only useful when they have some kind of side effect, such as storing a value, calling a function, or (this is esoteric) causing a fault in the program. Here are some more useful examples:

     x++;
     y = x + 25;
     printf ("Hello, user!");
     *cucumber;

The last of those statements, *cucumber;, could potentially cause a fault in the program if the value of cucumber is both not a valid pointer and has been declared as volatile.


Next: , Previous: Expression Statements, Up: Statements

4.2 Labels

You can use labels to identify a section of source code. A label consists of an identifier (such as those used for variable names) followed by a colon. Here is an example:

     treet:

You should be aware that label names do not interfere with other identifier names:

     int treet = 5;    /* treet the variable. */
     
     treet:            /* treet the label. */

ISO C mandates that a label must be followed by at least one statement. Although GCC will compile code that does not meet this requirement (and issue a warning in the process), you might want to avoid writing such code.


Next: , Previous: Labels, Up: Statements

4.3 The if Statement

You can use the if statement to conditionally execute a section of your program, based on the truth value of a given expression.

You can use the if statement to conditionally execute part of your program, based on the truth value of a given expression. Here is the general form of an if statement:

     if (test)
       then-statement
     else
       else-statement

If test evaluates to true, then then-statement is executed and else-statement is not. If test evaluates to false, then else-statement is executed and then-statement is not. The else clause is optional.

Here is an actual example:

     if (x == 10)
       printf ("x is 10");

If x == 10 evaluates to true, then the statement printf("x is 10"); is executed. If x == 10 evaluates to false, then the statement printf ("x is 10"); is not executed.

Here is an example using else:

     if (x == 10)
       printf("x is 10");
     else
       printf("x is not 10");

You can use a series of if statements to test for multiple conditions:

     if (x == 1)
       printf ("x is 1");
     else if (x == 2)
       printf ("x is 2");
     else if (x == 3)
       printf ("x is 3");
     else
       printf ("x is something else");


Next: , Previous: The if Statement, Up: Statements

4.4 The switch Statement

You can use the switch statement to compare one expression with others, and then execute a series of sub-statements based on the result of the comparisons. Here is the general form of a switch statement:

     switch(test)
       {
         case compare-1:
           if-equal-statement-1
         case compare-2:
           if-equal-statement-2
         ...
         default:
           default-statement
       }

The switch statement compares test to each of the cases of compare expressions, until it finds one that is equal to test. Then, the statements following the successful case are executed.

Optionally, you can specify a default case. If test doesn't match any of the specific cases listed prior to the default case, then the statements for the default case are executed. Traditionally, the default case goes after the specific cases, but that isn't required.

     switch (x)
       {
         case 0:
           printf ("x is 0");
           break;
         case 1:
           printf ("x is 1");
           break;
         default:
           printf ("x is something else");
           break;
       }

Notice the usage of the break statement in each of the cases. This is because, once a matching case is found, not only are its statements executed, but so are the statements for all following cases:

     int x = 0;
     
     switch (x)
       {
         case 0:
           printf ("x is 0");
         case 1:
           printf ("x is 1");
         default:
           printf ("x is something else");
       }

The output of that example is:

     x is 0
     x is 1
     x is something else

This is not always desired. Including a break statement at the end of each case redirects program flow to after the switch statement.

You can also specify a range of consecutive integer values in a single case label, like this:

     case low ... high:

This has the same effect as the corresponding number of individual case labels, one for each integer value from low to high, inclusive.

This feature is especially useful for ranges of ASCII character codes:

     case 'A' ... 'Z':

Be careful: Include spaces around the ...; otherwise it may be parsed incorrectly when you use it with integer values. For example, write this:

     case 1 ... 5:

instead of this:

     case 1...5:


Next: , Previous: The switch Statement, Up: Statements

4.5 The while Statement

The while statement is a loop statement with an exit test at the beginning of the loop. Here is the general form of the while statement:

     while (test)
       statement

The while statement first evaluates test. If test evaluates to true, statement is executed, and then test is evaluated again. statement continues to execute repeatedly as long as test is true after each execution of statement.

     int counter = 0;
     
     while (counter < 10)
       printf ("%d ", counter++);


Next: , Previous: The while Statement, Up: Statements

4.6 The do Statement

The do statement is a loop statement with an exit test at the end of the loop. Here is the general form of the do statement:

     do
       statement
     while (test);

The do statement first executes statement once. After that, it evaluates test. If test is true, then statement is executed again. statement continues to execute repeatedly as long as test is true after each execution of statement.

     int x = 0;
     
     do
       printf ("%d ", x++);
     while (x < 10);


Next: , Previous: The do Statement, Up: Statements

4.7 The for Statement

The for statement is a loop statement whose structure allows easy variable initialization, expression testing, and variable modification. It is very convenient for making counter-controlled loops. Here is the general form of the for statement:

     for (initialize; test; step)
       statement;

The for statement first evaluates the expression initialize. Then it evaluates the expression test. If test is false, then the loop ends and program control resumes after statement. Otherwise, if test is true, then statement is executed. Finally, step is evaluated, and the next iteration of the loop begins with evaluating test again.

Most often, initialize assigns values to one or more variables, which are generally used as counters, test compares those variables to a predefined expression, and step modifies those variables' values. Here is an example:

     int x;
     
     for (x = 1; x <= 10; x++)
       printf ("%d ", x);

This example prints the integers from 1 to 10, inclusive. First, it evaluates initialize, which assigns x the value 1. Then, as long as x is less than or equal to 10, the value of x is printed and incremented.

All three of the expressions in a for statement are optional, and any combination of the three is valid. Since the first expression is evaluated only once, it is perhaps the most commonly omitted expression. You could also write the above example as:

     int x = 1;
     
     for (; x <= 10; x++)
       printf ("%d ", x);

In this example, x receives its value prior to the beginning of the for statement.

If you leave out the test expression, then the for statement is an infinite loop (unless you put a break or goto statement somewhere in statement). This is like using 1 as test; it is never false.

     for (x = 1; ; x++)
       printf ("%d ", x);

This for statement starts printing numbers at 1 and then continues indefinitely, always printing x incremented by 1.

If you leave out the step expression, then no progress is made toward completing the loop—at least not as is normally expected with a for statement.

     for (x = 1; x <= 10;)
       printf ("%d ", x);

This example prints 1 over and over, indefinitely.

You can use the comma operator for monitoring and modifying multiple variables in a for statement:

     for (x = 1, y = 10; x <= 10, y >= 1; x++, y--)
       printf ("%d %d ", x, y);

This example assigns values to both x and y, checks that x is less than or equal to 10 and that y is greater than or equal to 1, and increments x and decrements y.


Next: , Previous: The for Statement, Up: Statements

4.8 Blocks

A block is a set of zero or more statements enclosed in braces. Often, a block is used as the body of an if statement or a loop statement, to group together statements that should all be treated as the body of an if or loop statement.

     for (x = 1; x <= 10; x++)
       {
         printf("x is %d\n", x);
     
         if ((x % 2) == 0)
           printf ("%d is even\n", x);
         else
           printf ("%d is odd\n", x);
       }

You can also put blocks inside other blocks:

     for (x = 1; x <= 10; x++)
       {
         if ((x % 2) == 0)
           {
             printf ("x is %d\n", x);
             printf ("%d is even\n", x);
           }
         else
           {
             printf ("x is %d\n", x);
             printf ("%d is odd\n", x);
           }
       }

You can declare variables inside a block; such variables are local to that block.

     {
       int x = 5;
       printf ("%d", x);
     }
     printf ("%d", x);   /* You can't do this! x exists only
                            in the preceding block. */


Next: , Previous: Blocks, Up: Statements

4.9 The Null Statement

The null statement is merely a semicolon alone.

     ;

A null statement does not do anything. It does not store a value anywhere. It does not cause time to pass during the execution of your program. It does not find new prime numbers, nor does it invent new low-calorie sugar substitutes.

Most often, a null statement is used as the body of a loop statement, or as one or more of the expressions in a for statement. Here is an example of a for statement that uses the null statement as the body of the loop (and also calculates the integer square root of n, just for fun):

     for (i = 1; i*i < n; i++)
       ;

Here is another example that uses the null statement as the body of a for loop and also produces output:

     for (x = 1; x <= 5; printf ("x is now %d\n", x), x++)
       ;


Next: , Previous: The Null Statement, Up: Statements

4.10 The goto Statement

You can use the goto statement to unconditionally jump to a different place in the program. Here is the general form of a goto statement:

     goto label;

You have to specify a label to jump to; when the goto statement is executed, program control jumps to that label. See Labels. Here is an example:

     goto end_of_program;
     ...
     end_of_program:

The label can be anywhere in the same function as the goto statement that jumps to it, but a goto statement cannot jump to a label in a different function.

You can use goto statements to simulate loop statements, but we do not recommend it—it makes the program harder to read, and GCC cannot optimize it as well. You should use for, while, and do statements instead of goto statements, when possible.


Next: , Previous: The goto Statement, Up: Statements

4.11 The break Statement

You can use the break statement to terminate a while, do, for, or switch statement. Here is an example:

     int x;
     
     for (x = 1; x <= 10; x++)
       {
         if (x == 8)
           break;
         else
           printf ("%d ", x);
       }

That example prints numbers from 1 to 7. When x is incremented to 8, x == 8 is true, so the break statement is executed, terminating the for loop prematurely.

If you put a break statement inside of a loop or switch statement which itself is inside of a loop or switch statement, then break only terminates the innermost loop or switch statement.


Next: , Previous: The break Statement, Up: Statements

4.12 The continue Statement

You can use the continue statement in loops to terminate an iteration of the loop and begin the next iteration. Here is an example:

     for (x = 0; x < 100; x++)
     {
       if (x % 2 == 0)
       {
         continue;
       }
       else
       {
         sum_of_odd_numbers + = x;
       }
     }

If you put a continue statement inside a loop which itself is inside a loop, then it affects only the innermost loop.


Previous: The continue Statement, Up: Statements

4.13 The return Statement

You can use the return statement to end the execution of a function and return program control to the function that called it. Here is the general form of the return statement:

     return return-value;

return-value is an optional expression to return. If the function's return type is void, then it is invalid to return an expression. You can, however, use the return statement without a return value.

If the function's return type is not the same as the type of return-value, and automatic type conversion cannot be performed, then returning return-value is invalid.

If the function's return type is not void and no return value is specified, then the return statement is valid unless the function is called in a context that requires a return value. For example:

     x = cosine (y);

In that case, the function cosine was called in a context that required a return value, so the value could be assigned to x.

Even in contexts where a return value is not required, it is a bad idea for a non-void function to omit the return value. With GCC, you can use the command line option -Wreturn-type to issue a warning if you omit the return value in such functions.

Here are some examples of using the return statement, in both a void and non-void function:

     void
     print_plus_five (int x)
     {
       printf ("%d ", x + 5);
       return;
     }
     int
     square_value (int x)
     {
       return x * x;
     }


Next: , Previous: Statements, Up: Top

5 Functions

You can write functions to separate parts of your program into distinct subprocedures. To write a function, you must at least create a function definition. It is a good idea also to have an explicit function declaration; you don't have to, but if you leave it out, then the default implicit declaration might not match the function itself, and you will get some compile-time warnings.

Every program requires at least one function, called main. That is where the program's execution begins.


Next: , Previous: Functions, Up: Functions

5.1 Function Declarations

You write a function declaration to specify the name of a function and its return type. A function declaration ends with a semicolon. Here is the general form:

     return-type function-name ( );

return-type can be any of the primitive data types (see Data Types), a structure type (see Structures), a union type (see Unions), an enumeration type (see Enumerations), a pointer type (see Pointers), or void. A return type of void indicates that the function does not return a value at all.

function-name can be any valid identifier (see Identifiers).

Here is an example of a function declaration for a function named double_value which has a return type of int:

     int double_value ( );

You should write the function declaration above the definition or first use of the function. You can put it in a header file and use the #include directive to include that function declartion in any source code files that use the function.


Next: , Previous: Function Declarations, Up: Functions

5.2 Function Prototypes

A function prototype is a function declaration with a list of the function parameters. Here is the general form:

     return-type function-name (parameter-list);

parameter-list consists of zero or more parameters, separated by commas. Usually, each parameter consists of a data type, and optionally a name for the parameter. The data type can be any of the primitive data types (see Data Types), a structure type (see Structures), a union type (see Unions), an enumeration type (see Enumerations), an array type (see Arrays), or a pointer type (see Pointers). You can also specify that a function have a variable number of parameters (see Variable Length Parameter Lists), or no parameters. If it has no parameters, either use void for the parameter list, or do not have a parameter list at all.

return-type and function-name are described in the function declaration section. See Function Declarations.

Here is an example of a function prototype with two parameters:

     int add_values (int, int);

If you include a name for a parameter, the name immediately follows the data type, like this:

     int add_values (int x, int y);

The parameter names can be any identifier (see Identifiers), and if you have more than one parameter, you can't use the same name more than once within a single prototype.

You should write the function prototype above the definition or first use of the function. You can put it in a header file and use the #include directive to include that function prototype in any source code files that use the function.


Next: , Previous: Function Prototypes, Up: Functions

5.3 Function Definitions

You write a function definition to specify what a function actually does. A function definition consists of information regarding the function's name, return type, and types and names of parameters, along with the body of the function. The function body is a series of statements enclosed in braces. Here is the general form of a function definition:

     return-type
     function-name (parameter-list)
     {
       function-body
     }

return-type and function-name are described in the section about function declarations (see Function Declarations), and you should use the same return types and function names in a function definition that you used in that function's declaration or prototype.

parameter-list is similar to the parameter list described in the function prototype section (see Function Prototypes), except you must include names for the parameters in a function definition.

Here is an simple example of a function definition—it takes two integers as its parameters and returns the sum of them as its return value:

     int
     add_values (int x, int y)
     {
       return x + y;
     }

You can also specify the type of the function parameters on the after the closing parentheses of the parameter list, like this:

     int
     add_values (x, y)
                 int x, int y;
     {
       return x + y;
     }


Next: , Previous: Function Definitions, Up: Functions

5.4 Calling Functions

You can call a function by using its name and supplying any needed parameters. Here is the general form of a function call:

     function-name (parameters)

A function call can make up an entire statement, or it can be used as a subexpression. Here is an example of the former case:

     print_integer ( 5 );

In that example, the function print_integer is called with the parameter 5. We can suppose that this function prints out the value 5 in some way, perhaps to the terminal.

Here is an example of a function call used as a subexpression; the function square_value returns the square of its parameter:

     a = square_integer ( 5 );

Supposing that the function square_integer works correctly, the above example assigns the value 25 to a.

If a function takes more than one parameter, then when you call it, you must separate parameters with commas. Here is an example, using a function that returns the sum of its two parameters:

     a = sum_of_integers ( 5, 10 );


Next: , Previous: Calling Functions, Up: Functions

5.5 Function Parameters

Function parameters can either be a constant value or a copy of variable, or the address of a variable. When you send a copy of a variable, you cannot change the original variable that was used as the parameter, only the copy. However, when you send the address of a variable, then you can manipulate the original variable using pointers.

This section describes both of those situations, and also how to write functions with variable length parameter lists—a function with an indefinite number of parameters.


Next: , Previous: Function Parameters, Up: Function Parameters

5.5.1 Pass By Value Parameters

There are two different situations in which a parameter is considered to be “passed by value”:

  1. When you pass a literal or some other constant value to a function.
  2. When you pass a non-pointer variable to a function.

In both of these cases, the function cannot modify the original value or variable that is passed to it. Of course, constant values cannot be modified at all, and when a variable is passed to a function, a copy of that variable is made. The function then operates on the copy. Here is an example:

     int x = 23;
     
     double_value ( x );
     
     ...
     
     /* Definition for double_value. */
     
     int double_value (int a)
     {
       a = 2 * a;
       return a;
     }

In that example, even though the parameter a is modified in the function double_value, the variable x that is passed to the function does not change. For the call to double_value to actually double the value of x, it would have to be incorporated into an assignment statement, like this:

     x = double_value ( x );


Next: , Previous: Pass By Value Parameters, Up: Function Parameters

5.5.2 Pass By Reference Parameters

You can pass a value to a function “by reference”, which means that, instead of sending a literal value or a copy of a variable, you send the address of a variable. This allows you to change the value of the variable from the function, which is something you cannot do when the parameter is passed by value.

To do this, you specify in the function definition (and prototype, if you use one) that the parameter is a pointer, like this:

     void swap_integers (int *a, int *b);

That example has two parameters, a and b, both of which are pointers to int values. When you call this function, instead of passing it literal values or variables, you pass it the addresses of variables, like this:

     int x = 5, y = 10;
     
     swap_integers ( &x, &y );

That way, in the function definition, you can actually change the values of x and y, because you passed the function the addresses of those variables. Here is the definition of the swap_integers function, which swaps the values held in two integer variables:

     void
     swap_integers (int *a, int *b)
     {
       int temp;
     
       temp = *a;
       *a = *b;
       *b = temp;
       return;
     }


Previous: Pass By Reference Parameters, Up: Function Parameters

5.5.3 Variable Length Parameter Lists

You can write a function that takes a variable number of arguments. To do this, the function needs to have at least one parameter of a known data type, but the remaining parameters are optional, and can vary in both quantity and data type.

You list the first parameter as normal, but then as the second parameter, use an ellipsis: .... Here is an example function prototype:

     int add_multiple_values (int number, ...);

To work with the optional parameters in the function definition, you need to use macro functions that are defined in the libary header file stdarg.h. So be sure to include that file. Those functions are described in The GNU C Library Reference Manual, but here is an example of using them:

     int
     add_multiple_values (int number, ...)
     {
       int counter, total = 0;
     
       /* Declare a variable of type va_list. */
       va_list parameters;
     
       /* Call the va_start function. */
       va_start (parameters, number);
     
       for (counter = 0; counter < number; counter++)
         {
           /* Get the values of the optional parameters. */
           total += va_arg (parameters, int);
         }
     
       /* End use of the parameters variable. */
       va_end (parameters);
     
       return total;
     }

To use optional parameters, you should have a way to know how many there are. This can vary, so it can't be hard-coded, but if you don't know how many optional parameters you have, then you could have difficulty knowing when to stop using the va_arg function. In the above example, the first parameter to the add_multiple_values function, number, was the number of optional parameters included. So, we might call the function like this:

     sum = add_multiple_values (3, 12, 34, 190);

The first parameter indicates how many optional parameters follow it.

Also, note that you don't actually need to use va_end function. In fact, in GNU C, it doesn't do anything at all. However, you might want to include it for portability to other compilers.


Next: , Previous: Function Parameters, Up: Functions

5.6 The main Function

Every program requires at least one function, called main. This is where the program begins executing. You do not need to write a declaration or prototype for main, but you do need to define it.

The return type for main is always int. You do not have to specify the return type for main, but you can. However, you cannot specify that it has a return type other than int. In general, you want to have main return 0. Returning other integers usually indicates that the program ended abnormally. (You are not required to explicitly return a value at all.)

You can write your main function to have no parameters, or to accept parameters from the command line. To have no parameters, you can either specify void as the parameter list, or simply leave it blank.

Here is a very simple main function with no parameters:

     int
     main (void)
     {
       printf ("Hi there!");
       return 0;
     }

To accept command line parameters, you need to have two parameters in the main function, int argc followed by char *argv[]. You can change the names of those parameters, but they must have those data types—int and array of pointers to char. argc is the number of command line parameters, including the name of the program itself. argv is an array of the parameters, as character strings. argv[0], the first element in the array, is the name of the program as typed at the command line; any following array elements are the parameters that followed the name of the program.

Here is an example main function that accepts command line parameters, and prints out what those parameters are:

     int
     main (int argc, char *argv[])
     {
       int counter;
     
       for (counter = 0; counter < argc; counter++)
         {
           printf ("%s \n", argv[counter]);
         }
     
       return 0;
     }


Next: , Previous: The main Function, Up: Functions

5.7 Recursive Functions

You can write a function that is recursive—a function that calls itself. Here is an example that computes the factorial of an integer:

     int
     factorial (int x)
     {
       if (x < 1)
         {
           return x;
         }
       else
         {
           return ( x * factorial (x - 1) );
         }
     }

Be careful that you do not write a function that is infinitely recursive. In the above example, once x is 1, the recursion stops. However, in the following example, the recursion (in theory) does not stop:

     int
     watermelon (int x)
     {
       return ( watermelon (x) );
     }


Previous: Recursive Functions, Up: Functions

You can define functions within other functions, a technique known as nesting functions.

Here is an example of a tail-recursive factorial function, defined using a nested function:

     int
     factorial (int x)
     {
       int
       factorial_helper (int a, int b)
       {
         if (a < 1)
         {
           return b;
         }
         else
         {
           return factorial_helper ((a - 1), (a * b));
         }
       }
     
       return factorial_helper (x, 1);
     }

Note that nested functions must be defined along with variable declarations at the beginning of a function, and all other statements follow.


Next: , Previous: Functions, Up: Top

GNU Free Documentation License

Version 1.2, November 2002
     Copyright © 2000,2001,2002 Free Software Foundation, Inc.
     59 Temple Place, Suite 330, Boston, MA  02111-1307, USA
     
     Everyone is permitted to copy and distribute verbatim copies
     of this license document, but changing it is not allowed.
  1. PREAMBLE

    The purpose of this License is to make a manual, textbook, or other functional and useful document free in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.

    This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.

    We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.

  2. APPLICABILITY AND DEFINITIONS

    This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The “Document”, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as “you”. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law.

    A “Modified Version” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.

    A “Secondary Section” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.

    The “Invariant Sections” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.

    The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words.

    A “Transparent” copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not “Transparent” is called “Opaque”.

    Examples of suitable formats for Transparent copies include plain ascii without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only.

    The “Title Page” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page” means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.

    A section “Entitled XYZ” means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.) To “Preserve the Title” of such a section when you modify the Document means that it remains a section “Entitled XYZ” according to this definition.

    The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License.

  3. VERBATIM COPYING

    You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.

    You may also lend copies, under the same conditions stated above, and you may publicly display copies.

  4. COPYING IN QUANTITY

    If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.

    If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.

    If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.

    It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.

  5. MODIFICATIONS

    You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:

    1. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission.
    2. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement.
    3. State on the Title page the name of the publisher of the Modified Version, as the publisher.
    4. Preserve all the copyright notices of the Document.
    5. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.
    6. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below.
    7. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice.
    8. Include an unaltered copy of this License.
    9. Preserve the section Entitled “History”, Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled “History” in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence.
    10. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the “History” section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission.
    11. For any section Entitled “Acknowledgements” or “Dedications”, Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein.
    12. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles.
    13. Delete any section Entitled “Endorsements”. Such a section may not be included in the Modified Version.
    14. Do not retitle any existing section to be Entitled “Endorsements” or to conflict in title with any Invariant Section.
    15. Preserve any Warranty Disclaimers.

    If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles.

    You may add a section Entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.

    You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.

    The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.

  6. COMBINING DOCUMENTS

    You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers.

    The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.

    In the combination, you must combine any sections Entitled “History” in the various original documents, forming one section Entitled “History”; likewise combine any sections Entitled “Acknowledgements”, and any sections Entitled “Dedications”. You must delete all sections Entitled “Endorsements.”

  7. COLLECTIONS OF DOCUMENTS

    You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.

    You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.

  8. AGGREGATION WITH INDEPENDENT WORKS

    A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an “aggregate” if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document.

    If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate.

  9. TRANSLATION

    Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.

    If a section in the Document is Entitled “Acknowledgements”, “Dedications”, or “History”, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title.

  10. TERMINATION

    You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

  11. FUTURE REVISIONS OF THIS LICENSE

    The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.

    Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.

ADDENDUM: How to use this License for your documents

To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:

       Copyright (C)  year  your name.
       Permission is granted to copy, distribute and/or modify this document
       under the terms of the GNU Free Documentation License, Version 1.2
       or any later version published by the Free Software Foundation;
       with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
       Texts.  A copy of the license is included in the section entitled ``GNU
       Free Documentation License''.

If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the “with...Texts.” line with this:

         with the Invariant Sections being list their titles, with
         the Front-Cover Texts being list, and with the Back-Cover Texts
         being list.

If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation.

If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.


Previous: GNU Free Documentation License, Up: Top

Index

Table of Contents