分类: C/C++
2014-06-28 10:11:23
This is the GNU C reference manual.
This is a reference manual for the C programming language as implemented by the GNU Compiler Collection (GCC). Specifically, this manual aims to document:
This manual describes C89 as its baseline. C99 features and GNU extensions are explicitly labeled as such.
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. (Some of the GNU extensions to C89 ended up, sometimes slightly modified, as standard language features in C99.)
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, so it is not included here.
Contributors who have helped with writing, editing, proofreading, ideas, typesetting, or administrative details include: Diego Andres Alvarez Marin, Nelson H. F. Beebe, Karl Berry, Robert Chassell, Antonio Diaz Diaz, Andreas Foerster, Denver Gingerich, Lisa Goldstein, Robert Hansen, Jean-Christophe Helary, Mogens Hetsholm, Teddy Hogeborn, Joe Humphries, J. Wren Hunt, Adam Johansen, Vladimir Kadlec, Benjamin Kagia, Bjorn Liencres, Steve Morningthunder, Aljosha Papsch, Matthew Plant, Richard Stallman, J. Otto Tennant, Ole Tetlie, Keith Thompson, T.F. Torrey, and James Youngman. Trevis Rothwell wrote most of the text and serves as project maintainer.
Some example programs are based on algorithms in Donald Knuth's The Art of Computer Programming.
Please send bug reports and suggestions to .
This chapter describes the lexical elements that make up C source code after preprocessing. These elements are called tokens. There are five types of tokens: keywords, identifiers, constants, operators, and separators. White space, sometimes required to separate tokens, is also described in this chapter.
Identifiers are sequences of characters used for naming variables, functions, new data types, and preprocessor macros. You can include letters, decimal digits, and the underscore character ‘_’ in identifiers.
The first character of an identifier cannot be a digit.
Lowercase letters and uppercase letters are distinct, such that foo and FOO are two different identifiers.
When using GNU extensions, you can also include the dollar sign character ‘$’ in identifiers.
Keywords are special identifiers reserved for use as part of the programming language itself. You cannot use them for any other purpose.
Here is a list of keywords recognized by ANSI C89:
auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while
ISO C99 adds the following keywords:
inline _Bool _Complex _Imaginary
and GNU extensions add these keywords:
__FUNCTION__ __PRETTY_FUNCTION__ __alignof __alignof__ __asm __asm__ __attribute __attribute__ __builtin_offsetof __builtin_va_arg __complex __complex__ __const __extension__ __func__ __imag __imag__ __inline __inline__ __label__ __null __real __real__ __restrict __restrict__ __signed __signed__ __thread __typeof __volatile __volatile__
In both ISO C99 and C89 with GNU extensions, the following is also recogized as a keyword:
restrict
A constant is a literal numeric or character value, such as 5 or `m'. All constants are of a particular data type; you can use type casting to explicitly specify the type of a constant, or let the compiler use the default type based on the value of the constant.
An integer constant is a sequence of digits, with an optional prefix to denote a number base.
If the sequence of digits is preceded by 0x or 0X (zero x or zero X), then the constant is considered to be hexadecimal (base 16). Hexadecimal values may use the digits from 0 to 9, as well as the letters a to f and A to F. Here are some examples:
0x2f 0x88 0xAB43 0xAbCd 0x1
If the first digit is 0 (zero), and the next character is not ‘x’ or ‘X’, then the constant is considered to be octal (base 8). Octal values may only use the digits from 0 to 7; 8 and 9 are not allowed. Here are some examples:
057 012 03 0241
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. Here are some examples:
459 23901 8 12
There are various integer data types, for short integers, long integers,
signed integers, and unsigned integers. You can force an integer constant
to be of a long and/or unsigned integer type by appending a sequence
of one or more letters to the end of the constant:
uUUnsigned integer type.
lLLong 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.)
Both ISO C99 and GNU C extensions add the integer types long long int and unsigned long long int. You can use two ‘L’s to get a long long int constant; add a ‘U’ to that and you have an unsigned long long int constant. For example: 45ULL.
A character constant is usually a single character enclosed within single quotation marks, such as 'Q'. A character constant is of type int by default.
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.
To use any of these escape sequences, enclose the sequence in single
quotes, and treat it as 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).
While the length of possible hexadecimal digit strings is unlimited, the number
of character constants in any given character set is not. (The much-used
extended ASCII character set, for example, has only 256 characters in it.)
If you try to use a hexadecimal value that is outside the range of characters,
you will get a compile-time error.
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.
Either the integer part or the fractional part may be omitted, but not
both. Here are some examples:
(In the third assignment statement, the integer constant 4 is automatically
converted from an integer value to a double value.)
Real number constants can also be followed by e or
E, and an integer exponent. The exponent can be either positive
or negative.
You can append a letter to the end of a real number constant
to cause it to be of a particular 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.
A string constant is a sequence of zero or more characters, digits,
and escape sequences enclosed within double quotation marks. A string
constant is of type “array of characters”. All string constants contain a
null termination character (\0) as their last character. Strings
are stored as arrays of characters, with no inherent size attribute.
The null termination character lets string-processing functions know
where the string ends.
Adjacent string constants are concatenated (combined) into
one string, with the null termination character added to the end of
the final concatenated string.
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 constants:
If a string is too long to fit on one line, you can use a backslash \
to break it up onto separate lines.
Adjacent strings are automatically concatenated, so you can also have string
constants span multiple lines by writing them as separate, adjacent, strings.
For example:
is the same as
To insert 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’.
prints
An operator is a special token that performs an operation, such as
addition or subtraction, on either one, two, or three operands.
Full coverage of operators can be found in a later
chapter. See .
A separator separates tokens. White space (see next section) is a
separator, but it is not a token. The other separators are all
single-character tokens themselves:
White space is the collective term used for several characters:
the space character, the tab character, the newline character, the
vertical tab character, and the form-feed character.
White space is ignored (outside of string
and character constants), and is therefore optional, except when it is
used to separate tokens. This means that
and
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 other separators and that which they separate.
Furthermore, wherever one space is allowed, any amount of white space
is allowed.
In string constants, spaces and tabs are not ignored; rather, they are
part of the string. Therefore,
is not the same as
The integer data types range in size from at least 8 bits to at least 32 bits.
The C99 standard extends this range to include integer sizes of at least 64 bits.
You should use integer types for storing whole number values (and the char
data type for storing characters). The sizes and ranges listed for these types
are minimums; depending on your computer platform, these sizes and ranges may be
larger.
While these ranges provide a natural ordering, the standard does
not require that any two types have a different range. For example,
it is common for int and long to have the same range.
The standard even allows signed char and long to have
the same range, though such platforms are very unusual.
Here are some examples of declaring and defining integer variables:
The first line declares an integer named foo but does not define
its value; it is left unintialized, and its value should not be assumed
to be anything in particular.
There are three data types that represent fractional numbers. While the
sizes and ranges of these types are consistent across most computer systems
in use today, historically the sizes of these types varied from system to
system. As such, the minimum and maximum 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; check your
system's float.h for specific numbers.
All floating point data types are signed; trying to use unsigned float,
for example, will cause a compile-time error.
Here are some examples of declaring and defining real number variables:
The first line declares a float named foo but does not define
its value; it is left unintialized, and its value should not be assumed
to be anything in particular.
The real number types provided in C are of finite precision, and
accordingly, not all real numbers can be represented exactly.
Most computer systems that GCC compiles for use a binary
representation for real numbers, which is unable to precisely
represent numbers such as, for example, 4.2. For this reason, we
recommend that you consider not comparing real numbers for exact
equality with the == operator, but rather check that real
numbers are within an acceptable tolerance.
There are other more subtle implications of these imprecise
representations; for more details, see David Goldberg's paper
What Every Computer Scientist Should Know About Floating-Point
Arithmetic and section 4.2.2 of Donald Knuth's The Art of
Computer Programming.
GCC introduced some complex number types as an
extension to C89. Similar features were introduced in
C99, but there were a number of
differences. We describe the standard complex number types first.
Complex types were introduced in C99. There are three complex
types:
The names here begin with an underscore and an uppercase letter in
order to avoid conflicts with existing programs' identifiers.
However, the C99 standard header file The GCC also introduced complex types as a GNU extension to C89, but the
spelling is different. The floating-point complex types in GCC's C89
extension are:
GCC's extension allow for complex types other than floating-point,
so that you can declare complex character types and complex integer
types; in fact __complex__ can be used with any of the
primitive data types. We won't give you a complete list of all
possibilities, 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.
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.
An enumeration is a custom data type used for storing constant integer
values and referring to them by names. By default, these values are
of type signed int; however, you can use the -fshort-enums
GCC compiler option to cause the smallest possible integer type to be
used instead. Both of these behaviors conform to the C89 standard,
but mixing the use of these options within the same program can
produce incompatibilities.
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.
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:
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:
In that example, kumquat is 0, raspberry is 1,
peach is 2, and plum is 4.
You can't use the same name for an enum as a struct or
union in the same scope.
You can declare variables of an enumeration type both when the
enumeration is defined and afterward. This example declares one
variable, named my_fruit of type enum fruit, all in
a single statement:
while this example declares the type and variable separately:
(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:
Enumerations are useful in conjunction with the switch
statement, because the compiler can warn you if you have failed to
handle one of the enumeration values. Using the example above, if
your code handles banana, apple and mango only
but not blueberry, GCC can generate a warning.
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.
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 between the union
keyword and the opening brace. This is syntactically optional, but if
you leave it out, you can't refer to that union data type later on
(without a typedef, see ).
Here is an example of defining a simple union for holding an integer
value and a floating point value:
That defines a union named numbers, which contains two
members, i and f, which are of type int and
float, respectively.
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.
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.
That example declares two variables of type union numbers,
first_number and second_number.
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.
That example declares two variables of type union numbers,
first_number and second_number.
You can initialize the first member of a union variable when you
declare it:
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:
or precede the member name with a period and assign a value
with the assignment operator, like this:
You can also initialize a union member when you declare the union
variable during the definition:
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.
Notice in that example that giving a value to the f member overrides
the value stored in the i member.
This size of a union is equal to the size of its largest member. Consider
the first union example from this section:
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.
A structure is a programmer-defined data type made up of
variables of other data types (possibly including other structure types).
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 (without a typedef, see ).
Here is an example of defining a simple structure for holding the
X and Y coordinates of a point:
That defines a structure type named struct point, which contains two
members, x and y, both of which are of type int.
Structures (and unions) may contain instances of other structures and
unions, but of course not themselves. It is possible for a structure
or union type to contain a field which is a pointer to the same type
(see ).
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.
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.
That example declares two variables of type struct point,
first_point and second_point.
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.
That example declares two variables of type struct point,
first_point and second_point.
You can initialize the members of a structure type to have certain
values when you declare structure variables.
If you do not initialize a structure variable, the effect depends on
whether it is has static storage (see ) or
not. If it is, members with integral types are initialized with 0 and
pointer members are initialized to NULL; otherwise, the value of the
structure's members is indeterminate.
One way to initialize a structure 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.
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. The first method is available in
C99 and as a C89 extension in GCC:
You can also omit the period and use a colon instead of ‘=’,
though this is a GNU C extension:
You can also initialize the structure variable's members when you declare
the variable during the structure definition:
You can also initialize fewer than all of a structure variable's members:
Here, x is initialized with 5, y is initialized with 0,
and p is initialized with NULL. The rule here is that y
and p are initialized just as they would be if they were static
variables.
Here is another example that initializes a structure's members which
are structure variables themselves:
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, we used 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.
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.
You can also access the members of a structure variable which is itself a
member of a structure variable.
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.
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.
Bit fields can be specified without a name in order to control which
actual bits within the containing unit are used. However,
the effect of this is not very portable and it is rarely useful.
You can also specify a bit field of size 0, which indicates that
subsequent bit fields not further bit fields should be packed into the
unit containing the previous bit field. This is likewise not
generally useful.
You may not take the address of a bit field with the address
operator & (see ).
The size of a structure type is equal to the sum of the size of all of its
members, possibly including padding to cause the structure type to align to
a particular byte boundary. The details vary depending on your computer
platform, but it would not be atypical to see structures padded to align
on four- or eight-byte boundaries. This is done in order to speed up
memory accesses of instances of the structure type.
As a GNU extension, GCC allows structures with no members. Such structures
have zero size.
If you wish to explicitly omit padding from your structure types (which may,
in turn, decrease the speed of structure memory accesses), then GCC provides
multiple methods of turning packing off. The quick and easy method is to
use the -fpack-struct compiler option. For more details on omitting
packing, please see the GCC manual which corresponds to your version of the
compiler.
An array is a data structure that lets you store one or more elements
consecutively in memory. In C, array elements are indexed beginning at
position zero, not one.
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:
For standard C code, the number of elements in an array must be positive.
As a GNU extension, the number of elements can be as small as zero.
Zero-length arrays are useful as the last element of a structure which is
really a header for a variable-length object:
Another GNU extension allows you to declare an array size using
variables, rather than only constants. For example, here is a function definition
that declares an array using its parameter as the number of elements:
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:
You don't have to explicitly initialize all of the array elements. For example, this code
initializes the first three elements as specified, and then initializes the last two
elements to a default value of zero:
When using either ISO C99, or C89 with GNU extensions, you can 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. Here is an example:
Or, using the assignment operator:
Both of those examples are equivalent to:
When using GNU extensions, you can 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:
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:
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:
In that example, only four elements are initialized, but the last one
initialized is element number 99, so there are 100 elements.
You can access the elements of an array by specifying the array name,
followed by the element index, enclosed in brackets. Remember that the array
elements are numbered starting with zero. Here is an example:
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:
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 each
dimension (a two-element array consisting of five-element arrays):
Multidimensional array elements are accessed by specifying the desired index
of both dimensions:
In our example, two_dimensions[0] is itself an array. The
element two_dimensions[0][2] is followed by
two_dimensions[0][3], not by two_dimensions[1][2].
You can use an array of characters to hold a string (see ).
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 simply initialize the array to a value,
and its size will then 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:
In each of these cases, the null character \0 is included at the
end of the string, even when not explicitly stated. (Note that if you
initialize a string using an array of individual characters, then the
null character is not guaranteed to be present. It might be,
but such an occurrence would be one of chance, and should not be relied
upon.)
After initialization, you cannot assign a new string literal to an array
using the assignment operator. For example, this
will not work:
However, there are functions in the GNU C library that perform operations
(including copy) on string arrays. You can also change one character at
a time, by accessing individual string elements as you would any other
array:
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 written to a memory
location that was not allocated for it.
You can create an array of a union type just as you can an array
of a primitive data type.
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:
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.
You can create an array of a structure type just as you can an array
of a primitive data type.
That example creates a 3-element array of struct point
variables called point_array. You can also initialize the
elements of a structure array:
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:
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.
Pointers hold memory addresses of stored 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.
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 ) before
the identifier. Here is the general form of a pointer declaration:
White space is not significant around the indirection operator:
Here is an example of declaring a pointer to hold the address of
an int variable:
Be careful, though: when declaring multiple pointers in the same statement, you must
explicitly declare each as a pointer, using the indirection operator:
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’:
Note the use of the address operator (see ), used
to get the memory address of a variable. 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:
The value stored in a pointer is an integral number: a location within
the computer's memory space. If you are so inclined, you can assign pointer
values explicitly using literal integers, casting them to the appropriate
pointer type. However, we do not recommend this practice unless you need
to have extremely fine-tuned control over what is stored in memory, and you
know exactly what you are doing. It would be all too easy to accidentally
overwrite something that you did not intend to. Most uses of this
technique are also non-portable.
It is important to note that if you do not initialize a pointer with
the address of some other existing object, it points nowhere in
particular and will likely make your program crash if you use it
(formally, this kind of thing is called undefined behavior).
You can create a pointer to a union type just as you can a pointer
to a primitive data type.
That example creates a new union type, union numbers, and
declares (and initializes the first member of) a variable of that type
named foo. Finally, it declares a pointer to the type
union numbers, and gives it the address of foo.
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 (see ). Continuing with the previous example, the
following example will change the value of the first member of
foo:
Now the i member in foo is 450.
You can create a pointer to a structure type just as you can a pointer
to a primitive data type.
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
(see ). Continuing with the previous
example, the following example will change the values of the members
of salmon:
Now the length and width members in salmon are
5.1 and 6.2, respectively.
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.
At some time later in your program you will want to complete
the type. You do this by defining it as you usually would:
This technique is commonly used to for linked lists:
There are two type qualifiers that you can prepend to your variable declarations
which change how the variables may be accessed: const and volatile.
const causes the variable to be read-only; after initialization, its
value may not be changed.
In addition to helping to prevent accidental value changes, declaring variables
with const can aid the compiler in code optimization.
volatile tells the compiler that the variable is explicitly changeable,
and seemingly useless accesses of the variable (for instance, via pointers) should
not be optimized away. You might use volatile variables to store data
that is updated via callback functions or signal handlers.
.
There are four storage class specifiers that you can prepend to your variable
declarations which change how the variables are stored in memory:
auto, extern, register, and static.
You use auto for variables which are local to a function, and whose
values should be discarded upon return from the function in which they are
declared. This is the default behavior for variables declared within functions.
register is nearly identical in purpose to auto, except that
it also suggests to the compiler that the variable will be heavily used, and,
if possible, should be stored in a register. You cannot use the
address-of operator to obtain the address of a variable declared with
register. This means that you cannot refer to the elements of
an array declared with storage class register. In fact the
only thing you can do with such an array is measure its size with
sizeof. GCC normally makes good choices about which values to
hold in registers, and so register is not often used.
static is essentially the opposite of auto: when applied to
variables within a function or block, these variables will retain their
value even when the function or block is finished. This is known as
static storage duration.
You can also declare variables (or functions) at the top level (that
is, not inside a function) to be static; such variables are
visible (global) to the current source file (but not other source
files). This gives an unfortunate double meaning to static;
this second meaning is known as static linkage. Two functions
or variables having static linkage in separate files are entirely
separate; neither is visible outside the file in which it is declared.
Uninitialized variables that are declared as extern are given
default values of 0, 0.0, or NULL, depending on
the type. Uninitialized variables that are declared as auto or
register (including the default usage of auto) are left
uninitialized, and hence should not be assumed to hold any particular
value.
extern is useful for declaring variables that you want to be visible to
all source files that are linked into your project. You cannot initialize a
variable in an extern declaration, as no space is actually allocated
during the declaration. You must make both an extern declaration
(typically in a header file that is included by the other source files which
need to access the variable) and a non-extern declaration which is where
space is actually allocated to store the variable. The extern declaration
may be repeated multiple times.
See , for related information.
Sometimes it is convenient to give a new name to a type. You can do this using
the typedef statement. See , for more information.
An expression consists of at least one operand and zero or more
operators. Operands are typed objects such as constants, variables,
and function calls that return values. Here are some examples:
Parentheses group subexpressions:
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).
Operators may have one, two, or three operands, depending on the operator.
Assignment operators store values in variables. C provides several
variations of assignment operators.
The standard assignment operator = simply stores the value of its
right operand in the variable specified by its left operand. As with
all assignment operators, the left operand (commonly referred to as the
“lvalue”) cannot be a literal or constant value.
Note that, unlike the other assignment operators described below, you
can use the plain assignment operator to store values of a structure
type.
Compound assignment operators perform an operation involving
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:
Adds the two operands together, and then assign the result of
the addition to the left operand.
Subtract the right operand from the left operand, and
then assign the result of the subtraction to the left operand.
Multiply the two operands together, and then assign the
result of the multiplication to the left operand.
Divide the left operand by the right operand, and assign
the result of the division to the left operand.
Perform modular division on the two operands, and assign the
result of the division to the left operand.
Perform a left shift operation on the left operand, shifting
by the number of bits specified by the right operand, and assign the
result of the shift to the left operand.
Perform a right shift operation on the left operand,
shifting by the number of bits specified by the right operand, and assign
the result of the shift to the left operand.
Perform a bitwise conjunction operation on the two operands, and
assign the result of the operation to the left operand.
Performs a bitwise exclusive disjunction operation on the two operands,
and assign the result of the operation to the left operand.
Performs a bitwise inclusive disjunction operation on the two
operands, and assign the result of the operation to the left operand.
Here is an example of using one of the compound assignment operators:
Since there are no side effects wrought by evaluating the variable
x asn an lvalue, the above code produces the same result as:
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. You can apply the increment operator either before or after
the operand. Here are some examples:
(Note that incrementing a pointer only makes sense if you have reason to believe
that the new pointer value will be a valid memory address.)
A prefix increment adds 1 before the operand is evaluated. A postfix
increment adds 1 after the operand is evaluated. In the previous
examples, changing the position of the operator would make no difference.
However, there are cases where it does make a difference:
The output of the above example is:
Likewise, you can subtract 1 from an operand using the decrement operator:
The concepts of prefix and postfix application apply here as with the
increment operator.
C provides operators for standard arithmetic operations: addition, subtraction,
multiplication, and division, along with modular division and negation. Usage
of these operators is straightforward; here are some examples:
You can add and subtract memory pointers, but you cannot multiply
or divide them.
Integer division of positive values truncates towards zero, so 5/3 is
1. However, if either operand is negative, the direction of rounding
is implementation-defined. for
information about overflow in signed integer division.
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 have the same result.
The operands must be expressions of a primitive data type.
Modular division returns the remainder produced after performing
integer division on the two operands. The operands must be of a
primitive integer type.
If the operand you use with the negative operator is of an unsigned data
type, then the result cannot negative, but rather is the
maximum value of the unsigned data type, minus the value of the operand.
Many systems use twos-complement arithmetic, and on such systems the
most negative value a signed type can hold is further away from zero
than the most positive value. For example, on one platform, this
program:
Produces this output:
Trivially, you can also apply a positive operator to a numeric
expression:
Numeric values are assumed to be positive unless explicitly made
negative, so this operator has no effect on program operation.
As a GNU extension, 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:
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.
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 following code examples, the variables x and y stand
for any two expressions of arithmetic types, or pointers.)
The equal-to operator == tests its two operands for equality.
The result is 1 if the operands are equal, and 0 if the operands are not equal.
The not-equal-to operator != tests its two operands for inequality.
The result is 1 if the operands are not equal, and 0 if the operands
are equal.
Comparing floating-point values for exact equality or inequality can
produce unexpected results. for more
information.
You can compare function pointers for equality or inequality; the
comparison tests if two function pointers point to the same function
or not.
Beyond equality and inequality, there are operators you can use to test
if one value is less than, greater than, less-than-or-equal-to, or
greater-than-or-equal-to another value. Here are some code samples that
exemplify usage of these operators:
Logical operators test the truth value of a pair of operands. Any
nonzero expression is considered true in C, while an expression that
evaluates to zero is considered false.
The logical conjunction operator && tests if two expressions
are both true. If the first expression is false, then the second
expression is not evaluated.
The logical conjunction operator || tests if at least one of
two expressions it true. If the first expression is true, then the
second expression is not evaluated.
You can prepend a logical expression with a negation operator
! to flip the truth value:
Since the second operand in a logical expression pair is not necessarily
evaluated, you can write code with perhaps unintuitive results:
If foo is ever zero, then not only would bar not be called,
but x would not be incremented. If you intend to increment x
regardless of the value of foo, you should do so outside of the
conjunction expression.
You use the left-shift operator << to shift its first operand's bits
to the left. The second operand denotes the number of bit places to shift.
Bits shifted off the left side of the value are discarded; new bits added
on the right side will all be 0.
Similarly, you use the right-shift operator >> to shift its
first operand's bits to the right. Bits shifted off the right side are
discarded; new bits added on the left side are usually 0, but
if the first operand is a signed negative value, then the added bits will
be either 0 or whatever value was previously in the leftmost bit
position.
For both << and >>, if the second operand is greater
than the bit-width of the first operand, or the second operand is
negative, the behavior is undefined.
You can use the shift operators to perform a variety of interesting
hacks. For example, given a date with the day of the month numbered
as d, the month numbered as m, and the year y, you
can store the entire date in a single number x:
You can then extract the original day, month, and year out of x
using a combination of shift operators and modular division:
C provides operators for performing bitwise conjunction, inclusive disjunction,
exclusive disjunction, and negation (complement).
Biwise conjunction examines each bit in its two operands, and when two
corresponding bits are both 1, the resulting bit is 1. All other resulting
bits are 0. Here is an example of how this works, using binary numbers:
Bitwise inclusive disjunction examines each bit in its two operands,
and when two corresponding bits are both 0, the resulting bit is 0. All
other resulting bits are 1.
Bitwise exclusive disjunction examines each bit in its two operands, and when
two corresponding bits are different, the resulting bit is 1. All other resulting
bits are 0.
Bitwise negation reverses each bit in its operand:
In C, you can only use these operators with operands of an integer (or character)
type, and for maximum portability, you should only use the bitwise negation operator
with unsigned integer types. Here are some examples of using these operators in
C code:
You can use the address operator & to obtain the memory address of
an object.
It is not necessary to use this operator to obtain the address of
a function, although you can:
Function pointers and data pointers are not compatible, in the sense
that you cannot expect to store the address of a function into a data
pointer, and then copy that into a function pointer and call it
successfully. It might work on some systems, but it's not a portable
technique.
As a GNU extension to C89, you can also obtain the address of a label
with the label address operator &&. The result is a
void* pointer which can be used with goto. See .
Given a memory address stored in a pointer, you can use the indirection
operator * to obtain the value stored at the address. (This is called
dereferencing the pointer.)
Avoid using dereferencing pointers that have not been initialized to
a known memory location.
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. When the operand is a type name, it must be enclosed in
parentheses. Here are some examples:
The result of the sizeof operator is of a type called size_t,
which is defined in the header file The size_t type is often a convenient type for a loop index,
since it is guaranteed to be able to hold the number of elements in
any array; this is not the case with int, for example.
The sizeof operator can be used to automatically compute the
number of elements in an array:
There are two cases where this technique does not work. The first is
where the array element has zero size (GCC supports zero-sized
structures as a GNU extension). The second is where the array is in
fact a function parameter (see ).
You can use a type cast to explicitly cause an expression to be of a specified
data type. 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:
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. Explicitly casting the result
of the division to float does no good, because the computed
value of y/z is already 2.
To fix this problem, you need to convert one of the operands to a
floating-point type before the division takes place:
Here, a floating-point value close to 2.333... is assigned to x.
Type casting only works with scalar types (that is, integer,
floating-point or pointer types). Therefore, this is not allowed:
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, supposing an integer array called my_array:
The array subscript expression A[i] is defined as being
identical to the expression (*((A)+(i))). This means that many
uses of an array name are equivalent to a pointer expression. It also
means that you cannot subscript an array having the register
storage class.
A call to any function which returns a value is an expression.
You use the comma operator , to separate two (ostensibly related) expressions.
For instance, the first expression might produce a value that is used by the second
expression:
More commonly, the comma operator is used in for statements, like
this:
This lets you conveniently set, monitor, and modify multiple control
expressions for the for statement.
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, then
the compiler will
interpret that as calling the function with an extra parameter.
If you want to use the comma operator in a function argument, you need
to put parentheses around it. That's because commas in a function
argument list have a different meaning: they separate arguments.
Thus,
is interpreted as a function call with four arguments, but
is a function call with just three arguments. (The second argument is
(y=47, x).)
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.
You can also access the members of a structure or union variable via
a pointer by using the indirect member access operator ->.
x->y is equivalent to (*x).y.
See .
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. Here's an example:
If expression a is true, then expression b is evaluated
and the result is the value of b. Otherwise, expression
c is evaluated and the result is c.
Expressions b and c must be compatible. That is, they
must both be
Alternatively, one operand is a pointer and the other is a
void* pointer.
Here is an example
Here, if x equals 5, then a will receive
the value of y. Otherwise, a will receive the value of
z. This can be considered a shorthand method for writing a simple
if...else statement. The following example will
accomplish the same task as the previous one:
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.
As a GNU C extension, you can build an expression using compound
statement enclosed in parentheses. This allows you to included
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:
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:
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:
If you don't know the type of the operand, you can still do this, but you
must use typeof expressions or type naming.
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.
When an expression contains multiple operators, such as a + b *
f(), the operators are grouped based on rules of precedence.
For instance, the meaning of that expression is to call the function
f with no arguments, multiply the result by b, then add
that result to a. That's what the C rules of operator
precedence determine for this expression.
The following is a list of types of expressions, presented in order of
highest precedence first. Sometimes two or more operators have equal
precedence; all those operators are applied from left to right
unless stated otherwise.
The above list is somewhat dry and is apparently straightforward, but
it does hide some pitfalls. Take this example:
Here p is incremented as a side effect of the expression, but
foo takes the value of *(p++) rather than (*p)++,
since the unary operators bind right to left. There are other
examples of potential surprises lurking behind the C precedence
table. For this reason if there is the slightest risk of the reader
misunderstanding the meaning of the program, you should use
parentheses to make your meaning clear.
In C you cannot assume that multiple subexpressions are evaluated in
the order that seems natural. For instance, consider the expression
++a * f(). Does this increment a before or after
calling the function f? The compiler could do it in either
order, so you cannot make assumptions.
This manual explains the semantics of the C language in the abstract.
However, an actual compiler translates source code into specific
actions in an actual computer, and may re-order operations for the
sake of efficiency. The correspondence between the program you write
and the things the computer actually does are specified in terms of
side effects and sequence points.
A side effect is one of the following:
These are essentially the externally-visible effects of running a
program. They are called side effects because they are effects of
expression evalation beyond the expression's actual resulting value.
The compiler is allowed to perform the operations of your program in
an order different to the order implied by the source of your program,
provided that in the end all the necessary side effects actually take
place. The compiler is also allowed to entirely omit some operations;
for example it's allowed to skip evaluating part of an expression if
it can be certain that the value is not used and evaluating that part
of the expression won't produce any needed side effects.
Another requirement on the compiler is that side effects should take
place in the correct order. In order to provide this without
over-constraining the compiler, the C89 and C90 standards specify a
list of sequence points. A sequence point is one of the
following:
At a sequence point, all the side effects of previous expression
evaluations must be complete, and no side effects of later evaluations
may have taken place.
This may seem a little hard to grasp, but there is another way to
consider this. Imagine you wrote a library (some of whose functions
are external and perhaps others not) and compiled it, allowing someone
else to call one of your functions from their code. The definitions
above ensure that, at the time they call your function, the data they
pass in has values which are consistent with the behaviour specified
by the abstract machine, and any data returned by your function has a
state which is also consistent with the abstract machine. This
includes data accessible via pointers (i.e. not just function
parameters and identifiers with external linkage).
The above is a slight simplification, since compilers exist that
perform whole-program optimisation at link time. Importantly however,
although they might perform optimisations, the visible side effects of
the program must be the same as if they were produced by the abstract
machine.
The code fragment
is quite normal and no doubt occurs in many programs. However, the
quite similar code fragment
is a little harder to understand; what is the final value of i?
The C standards (both C89 and C99) both forbid this construct in
conforming programs.
Between two sequence points,
The first of these two conditions forbids expressions like
foo(x=2, ++x). The second condition forbids expressions like
a[i++] = i.
int x=0; foo(++x, ++x)Not allowed in a conforming program; modifies x twice before
argument evaluation is complete.
Let's go back to the example we used to introduce the problem of the
order of evaluation, ++a * f(). Suppose the code actually
looks like this:
Is this code allowed in a standard-conforming program? Although the
expression in foo modifies a twice, this is not a
problem. Let's look at the two possible cases.
The right operand f() is evaluated firstSince f returns a value other than void, it must contain a
return statement. Therefore, there is a sequence point at the
end of the return expression. That comes between the modification to
a that f makes and the evaluation of the left operand.
So, we see that our program is standard-conforming. Notice that the
above argument does not actually depend on the details of the body of
the function f. It only depends on the function containing
something ending in a sequence point – in our example this is a
return statement, but an expression statement or a full declarator
would do just as well.
However, the result of executing this code depends on the order of
evaluation of the operands of *. If the left-hand operand is
evaluated first, foo returns 6. Otherwise, it returns 303.
The C standard does not specify in which order the operands should be
evaluated, and also does not require an implementation either to
document the order or even to stick to one order. The effect of this
code is unspecified, meaning that one of several specific
things will happen, but the C standards do not say which.
Signals are mainly documented in the GNU C Library manual rather than
this document, even though the C standards consider the compiler and
the C library together to be “the implementation”.
When a signal is received, this will happen between sequence points.
Side effects on volatile objects prior to the previous sequence
point will have occurred, but other updates may not have occurred
yet. This even applies to straight assignments, such as x=0;,
because the code generated for that statement may require more than
one instruction, meaning that it can be interrupted part-way through
by the delivery of a signal.
The C standard is quite restrictive about what data access can occur
within a signal handler. They can of course use auto
variables, but in terms of reading or writing other objects, they must
be volatile sig_atomic_t. The volatile type qualifier
ensures that access to the variable in the other parts of the program
doesn't span sequence points and the use of the sig_atomic_t
type ensures that changes to the variable are atomic with respect to
signal delivery.
The POSIX standard also allows a small number of library functions to
be called from a signal handler. These functions are referred to as
the set of async-signal-safe functions. If your program is
intended to run on a POSIX system but not on other systems, you can
safely call these from your signal handler too.
You write statements to cause actions and to control flow within your
programs. You can also write statements that do not do anything at all,
or do things that are uselessly trivial.
You can use labels to identify a section of source code for use with a
later goto (see ). A label consists of an
identifier (such as those used for variable names) followed by a
colon. Here is an example:
You should be aware that label names do not interfere with other
identifier names:
The ISO C standard mandates that a label must be followed by at least
one statement, possibly a null statement (see ).
GCC will compile code that does not meet this requirement, but be
aware that if you violate it, your code may have portability issues.
You can turn any expression into a statement by adding a semicolon to
the end of the expression. Here are some examples:
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:
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.
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 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 evaluates to true, then the statement
puts ("x is 10"); is executed. If x == 10 evaluates to
false, then the statement puts ("x is 10"); is not executed.
Here is an example using else:
You can use a series of if statements to test for multiple
conditions:
This function calculates and displays the date of Easter for the given year y:
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:
The switch statement compares test to each of the
compare expressions, until it finds one that is
equal to test. Then, the statements following the successful
case are executed. All of the expressions compared must be of an integer
type, and the compare-N expressions must be of a constant integer
type (e.g., a literal integer or an expression built of literal integers).
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 is put after the specific cases, but that isn't required.
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:
The output of that example is:
This is often not desired. Including a break statement at the
end of each case redirects program flow to after the switch statement.
As a GNU C extension, you can also specify a range of consecutive integer
values in a single case label, like this:
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:
Be careful to include spaces around the ...; otherwise it
may be parsed incorrectly when you use it with integer values. For
example, write this:
instead of this:
It is common to use a switch statement to handle various
possible values of errno. In this case a portable program
should watch out for the possibility that two macros for errno
values in fact have the same value, for example EWOULDBLOCK and
EAGAIN.
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:
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.
This example prints the integers from zero through nine:
A break statement can also cause a while loop to exit.
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:
The do statement first executes statement. 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.
This example also prints the integers from zero through nine:
A break statement can also cause a do loop to exit.
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:
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 another example that prints the integers
from zero through nine:
First, it evaluates initialize, which assigns x the value
0. Then, as long as x is less than 10, the value of x
is printed (in the body of the loop). Then x is incremented in
the step clause and the test re-evaluated.
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:
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.
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.
This example prints the number 1 over and over, indefinitely:
Perhaps confusingly, you cannot use the comma operator (see ) for monitoring multiple variables in a for
statement, because as usual the comma operator discards the result of
its left operand. This loop:
Outputs:
If you need to test two conditions, you will need to use the &&
operator:
A break statement can also cause a for loop to exit.
Here is an example of a function that computes the summation of squares, given a
starting integer to square and an ending integer to square:
A block is a set of zero or more statements enclosed in braces.
Blocks are also known as compound statements. Often, a block is
used as the body of an if statement or a loop statement, to
group statements together.
You can also put blocks inside other blocks:
You can declare variables inside a block; such variables are local to
that block. In C89, declarations must occur before other statements,
and so sometimes it is useful to introduce a block simply for this
purpose:
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.
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):
Here is another example that uses the null statement as the body
of a for loop and also produces output:
A null statement is also sometimes used to follow a label that would
otherwise be the last thing in a block.
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:
You have to specify a label to jump to; when the goto statement
is executed, program control jumps to that label. See . Here
is an example:
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.
As an extension, GCC allows a goto statement to jump to an address
specified by a void* variable. To make this work, you also
need to take the address of a label by using the unary operator
&& (not &). Here is a contrived example:
You can use the break statement to terminate a while, do,
for, or switch statement. Here is an example:
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, the
break only terminates the innermost loop or switch 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:
If you put a continue statement inside a loop which itself is
inside a loop, then it affects only the innermost loop.
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-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:
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:
You can use the typedef statement to create new names for data
types. Here is the general form of the typedef statement:
old-type-name is the existing name for the type, and may consist
of more than one token (e.g., unsigned long int).
new-type-name is the resulting new name for the type, and must
be a single identifier. Creating this new name for the type does
not cause the old name to cease to exist. Here are some examples:
In the case of custom data types, you can use typedef to make a
new name for the type while defining the type:
To make a type definition of an array, you first provide the type of the element, and
then establish the number of elements at the end of the type definition:
When selecting names for types, you should avoid ending your type names with
a _t suffix. The compiler will allow you to do this, but the
POSIX standard reserves use of the _t suffix for standard library
type names.
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.
You write a function declaration to specify the name of a function, a
list of parameters, and the function's return type. A function declaration
ends with a semicolon. Here is the general form:
return-type indicates the data type of the value returned by the function.
You can declare a function that doesn't return anything by using the return
type void.
function-name can be any valid identifier (see ).
parameter-list consists of zero or more parameters, separated by commas.
A typical parameter consists of a data type and an optional name for the
parameter. You can also declare a function that has a variable number of
parameters (see ), or no parameters using
void. Leaving out parameter-list entirely also indicates
no parameters, but it is better to specify it explicitly with void.
Here is an example of a function declaration with two parameters:
If you include a name for a parameter, the name immediately follows the
data type, like this:
The parameter names can be any identifier (see ), and if you
have more than one parameter, you can't use the same name more than
once within a single declaration. The parameter names in the
declaration need not match the names in the definition.
You should write the function declaration above the first use of
the function. You can put it in a header file and use the #include
directive to include that function declaration in any source code files that
use the function.
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; in fact it is simply a block (see ).
Here is the general form of a function definition:
return-type and function-name are the same as what you use
in the function declaration (see ).
parameter-list is the same as the parameter list used in the function
declaration (see ), 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:
For compatibility with the original design of C, you can also specify
the type of the function parameters after the closing
parenthesis of the parameter list, like this:
However, we strongly discourage this style of coding; it can cause
subtle problems with type casting, among other problems.
You can call a function by using its name and supplying any needed parameters.
Here is the general form of a function call:
A function call can make up an entire statement, or it can be used as a
subexpression. Here is an example of a standalone function call:
In that example, the function ‘foo’ is called with the
parameter 5.
Here is an example of a function call used as a subexpression:
Supposing that the function ‘square’ squares its parameter, the
above example assigns the value 25 to a.
If a parameter takes more than one argument, you separate parameters with commas:
Function parameters can be any expression—a literal value, a value stored in
variable, an address in memory, or a more complex expression built by
combining these.
Within the function body, the parameter is a local copy of the value passed into
the function; you cannot change the value passed in by changing the local copy.
In that example, even though the parameter a is modified in the
function ‘foo’, the variable x that is passed to
the function does not change. If you wish to use the function to change
the original value of x, then you would have to incorporate the
function call into an assignment statement:
If the value that you pass to a function is a memory address (that is, a pointer), then you
can access (and change) the data stored at the memory address. This
achieves an effect similar to pass-by-reference in
other languages, but is not the same: the memory address is simply a
value, just like any other value, and cannot itself be changed. The
difference between passing a pointer and passing an integer lies in
what you can do using the value within the function.
Here is an example of calling a function with a pointer parameter:
The formal parameter for the function is of type pointer-to-int, and we
call the function by passing it the address of a variable of type int. By
dereferencing the pointer within the function body, we can both see and change
the value stored in the address. The above changes the value of
a to ‘57’.
Even if you don't want to change the value stored in the address, passing the
address of a variable rather than the variable itself can be useful if the
variable type is large and you need to conserve memory space or limit
the performance impact of parameter copying. For example:
In this case, unless you are working on a computer with very large memory
addresses, it will take less memory to pass a pointer to the structure
than to pass an instance of the structure.
One type of parameter that is always passed as a pointer is any sort
of array:
In this example, calling the function foo with the parameter a
does not copy the entire array into a new local parameter within foo;
rather, it passes x as a pointer to the first element in x.
Be careful, though: within the function, you cannot use sizeof to determine
the size of the array x—sizeof instead tells you the size of the
pointer x. Indeed, the above code is equivalent to:
Explicitly specifying the length of the array in the
parameter declaration will not help. If you really need to pass an
array by value, you can wrap it in a struct, though doing this
will rarely be useful (passing a const-qualified pointer is
normally sufficient to indicate that the caller should not modify the
array).
You can write a function that takes a variable number of arguments; these are
called variadic functions. 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 initial parameters as normal, but then after that, use an
ellipsis: ‘...’. Here is an example function prototype:
To work with the optional parameters in the function definition, you need
to use macros that are defined in the library header file
‘ Here is an example:
To use optional parameters, you need to 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’, is the number of optional parameters actually passed.
So, we might call the function like this:
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, with GCC it doesn't do anything at all. However, you might want
to include it to maximize compatibility with other compilers.
See .
You can also call a function identified by a pointer. The
indirection operator * is optional when doing this.
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, the return value from main indicates the program's
exit status. A value of zero or EXIT_SUCCESS indicates success
and EXIT_FAILURE indicates an error. Otherwise, the significance of
the value returned is implementation-defined.
Reaching the } at the end of main without a return, or
executing a return statement with no value (that is,
return;) are both equivalent. In C89, the effect of this is
undefined, but in C99 the effect is equivalent to return 0;.
You can write your main function to have no parameters (that
is, as int main (void), or to accept parameters from the
command line. Here is a very simple main function with no
parameters:
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:
You can write a function that is recursive—a function that calls
itself. Here is an example that computes the factorial of an integer:
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 does not stop until the program is interrupted
or runs out of memory:
Functions can also be indirectly recursive, of course.
You can define a function to be static if you want it to be callable only
within the source file where it is defined:
This is useful if you are building a reusable library of functions and need to
include some subroutines that should not be callable by the end user.
Functions which are defined in this way are said to have static
linkage. Unfortunately the static keyword has multiple
meanings; .
As a GNU C extension, 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:
Note that nested functions must be defined along with variable
declarations at the beginning of a function, and all other statements
follow.
Now that we have seen all of the fundamental elements of C programs, it's time
to look at the big picture.
A C program may exist entirely within a single source file, but more commonly, any non-trivial
program will consist of several custom header files and source files, and will also include
and link with files from existing libraries.
By convention, header files (with a “.h” extension) contain variable and function
declarations, and source files (with a “.c” extension) contain the corresponding
definitions. Source files may also store declarations, if these declarations are
not for objects which need to be seen by
other files. However, header files almost certainly should not contain any definitions.
For example, if you write a function that computes square roots, and you wanted this function
to be accessible to files other than where you define the function, then you would put the
function declaration into a header file (with a “.h” file extension):
This header file could be included by other source files which need to use your function,
but do not need to know how it was implemented.
The implementation of the function would then go into a corresponding source file
(with a “.c” file extension):
Scope refers to what parts of the program can “see” a declared object. A declared
object can be visible only within a particular function, or within a particular file,
or may be visible to an entire set of files by way of including header files and
using extern declarations.
Unless explicitly stated otherwise, declarations made at the top-level of a file
(i.e., not within a function) are visible to the entire file, including from within
functions, but are not visible outside of the file.
Declarations made within functions are visible only within those functions.
A declaration is not visible to declarations that came before it; for example:
will work, but:
will not.
See , for more information on changing the scope of
declared objects. Also see .
To conclude our description of C, here is a complete program written in C,
consisting of both a C source file and a header file. This
program is an expanded version of the quintessential “hello world” program, and
serves as an example of how to format and structure C code for use in programs
for FSF Project GNU. (You can always download the most recent version of this
program, including sample makefiles and other examples of how to produce GNU
software, from )
This program uses features of the preprocessor; for a description of preprocessor
macros, see The C Preprocessor, available as part of the GCC documentation.
[This appendix, written principally by Paul Eggert, is from the GNU Autoconf manual. We
thought that it would be helpful to include here. –TJR]
In practice many portable C programs assume that signed integer overflow wraps
around reliably using two's complement arithmetic. Yet the C standard
says that program behavior is undefined on overflow, and in a few cases
C programs do not work on some modern implementations because their
overflows do not wrap around as their authors expected. Conversely, in
signed integer remainder, the C standard requires overflow
behavior that is commonly not implemented.
In languages like C, unsigned integer overflow reliably wraps around;
e.g., UINT_MAX + 1 yields zero.
This is guaranteed by the C standard and is
portable in practice, unless you specify aggressive,
nonstandard optimization options
suitable only for special applications.
In contrast, the C standard says that signed integer overflow leads to
undefined behavior where a program can do anything, including dumping
core or overrunning a buffer. The misbehavior can even precede the
overflow. Such an overflow can occur during addition, subtraction,
multiplication, division, and left shift.
Despite this requirement of the standard, many C programs
assume that signed integer overflow silently wraps around modulo a
power of two, using two's complement arithmetic, so long as you cast the
resulting value to a signed integer type or store it into a signed
integer variable. If you use conservative optimization flags, such
programs are generally portable to the vast majority of modern
platforms, with a few exceptions discussed later.
For historical reasons the C standard also allows implementations with
ones' complement or signed magnitude arithmetic, but it is safe to
assume two's complement nowadays.
Also, overflow can occur when converting an out-of-range value to a
signed integer type. Here a standard implementation must define what
happens, but this might include raising an exception. In practice all
known implementations support silent wraparound in this case, so you need
not worry about other possibilities.
There has long been a tension between what the C standard requires for
signed integer overflow, and what C programs commonly assume. The
standard allows aggressive optimizations based on assumptions that
overflow never occurs, but many practical C programs rely on overflow
wrapping around. These programs do not conform to the standard, but
they commonly work in practice because compiler writers are
understandably reluctant to implement optimizations that would break
many programs, unless perhaps a user specifies aggressive optimization.
The C Standard says that if a program has signed integer overflow its
behavior is undefined, and the undefined behavior can even precede the
overflow. To take an extreme example:
\?Question mark character.
\'Single quotation mark.
\"Double quotation mark.
\aAudible alert.
\bBackspace character.
\e
\fForm feed.
\nNewline character.
\rCarriage return.
\tHorizontal tab.
\vVertical tab.
\o, \oo, \oooOctal number.
\xh, \xhh, \xhhh, ...Hexadecimal number.
Next: ,
Previous: ,
Up:
1.3.3 Real Number Constants
double a, b, c, d, e, f;
a = 4.7;
b = 4.;
c = 4;
d = .7;
e = 0.7;
double x, y;
x = 5e2; /* x is 5 * 100, or 500.0. */
y = 5e-2; /* y is 5 * (1/100, or 0.05. */
Previous: ,
Up:
1.3.4 String Constants
/* This is a single string constant. */
"tutti frutti ice cream"
/* These string constants will be concatenated, same as above. */
"tutti " "frutti" " ice " "cream"
/* This one uses two escape sequences. */
"\"hello, world!\""
"Today's special is a pastrami sandwich on rye bread with \
a potato knish and a cherry soda."
"Tomorrow's special is a corned beef sandwich on "
"pumpernickel bread with a kasha knish and seltzer water."
"Tomorrow's special is a corned beef sandwich on \
pumpernickel bread with a kasha knish and seltzer water."
printf ("potato\nknish");
potato
knish
Next: ,
Previous: ,
Up:
1.4 Operators
Next: ,
Previous: ,
Up:
1.5 Separators
( ) [ ] { } ; , . :
Previous: ,
Up:
1.6 White Space
#include
#include
/* 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 ;
/* These two statements are functionally identical. */
x++;
x
++ ;
"potato knish"
"potato knish"
Next: ,
Previous: ,
Up:
2 Data Types
Next: ,
Up:
2.1 Primitive Data Types
Next: ,
Up:
2.1.1 Integer Types
The 8-bit signed char data type can hold integer values in
the range of −128 to 127.
The 8-bit unsigned char data type can hold integer values in
the range of 0 to 255.
Depending on your system, the char data type is defined as
having the same range as either the signed char or the unsigned char
data type (they are three distinct types, however). By convention,
you should use the char data type
specifically for storing ASCII characters (such as `m'), including escape
sequences (such as `\n').
The 16-bit short int data type can hold integer values in the
range of −32,768 to 32,767. You may also refer to this data type as
short, signed short int, or signed short.
The 16-bit unsigned short int data type can hold integer values
in the range of 0 to 65,535. You may also refer to this data type
as unsigned short.
The 32-bit int data type can hold integer values in the range
of −2,147,483,648 to 2,147,483,647. You may also refer to this data type
as signed int or signed.
The 32-bit unsigned int data type can hold integer values in
the range of 0 to 4,294,967,295. You may also refer to this data type
simply as unsigned.
The 32-bit long int data type can hold integer values in
the range of at least −2,147,483,648 to 2,147,483,647. (Depending on
your system, this data type might be 64-bit, in which case its range is
identical to that of the long long int data type.) You may also
refer to this data type as long, signed long int,
or signed long.
The 32-bit unsigned long int data type can hold integer values
in the range of at least 0 to 4,294,967,295. (Depending on your
system, this data type might be 64-bit, in which case its range is
identical to that of the unsigned long long int data type.) You may
also refer to this data type as unsigned long.
The 64-bit long long int data type can hold integer values in
the range of −9,223,372,036,854,775,808 to 9,223,372,036,854,775,807. You
may also refer to this data type as long long,
signed long long int or signed long long. This type is
not part of C89, but is both part of C99 and a GNU C extension.
The 64-bit unsigned long long int data type can hold integer
values in the range of at least 0 to 18,446,744,073,709,551,615. You may
also refer to this data type as unsigned long long. This type is
not part of C89, but is both part of C99 and a GNU C extension.
int foo;
unsigned int bar = 42;
char quux = 'a';
Next: ,
Previous: ,
Up:
2.1.2 Real Number Types
The float data type is the smallest of the three floating point
types, if they differ in size at all. Its minimum value is stored in
the FLT_MIN, and should be no greater than 1e-37. Its maximum
value is stored in FLT_MAX, and should be no less than 1e37.
The double data type is at least as large as the float
type, and it may be larger. Its minimum value is stored in
DBL_MIN, and its maximum value is stored in DBL_MAX.
The long double data type is at least as large as the
float type, and it may be larger. Its minimum value is stored in
LDBL_MIN, and its maximum value is stored in LDBL_MAX.
float foo;
double bar = 114.3943;
Previous: ,
Up:
2.1.3 Complex Number Types
Next: ,
Up:
Expands to _Complex. This allows a variable to be declared as
double complex which seems more natural.
A constant of type const float _Complex having the value of the
imaginary unit normally referred to as i.
#include
Previous: ,
Up:
The __complex__ float data type has two components: a real
part and an imaginary part, both of which are of the float data type.
The __complex__ int data type also has two components: a
real part and an imaginary part, both of which are of the int data
type.
__complex__ float a = 4 + 3i;
float b = __real__ a; /* b is now 4. */
float c = __imag__ a; /* c is now 3. */
Next: ,
Previous: ,
Up:
2.2 Enumerations
Next: ,
Up:
2.2.1 Defining Enumerations
enum fruit {grape, cherry, lemon, kiwi};
enum more_fruit {banana = -17, apple, blueberry, mango};
enum yet_more_fruit {kumquat, raspberry, peach,
plum = peach + 2};
Previous: ,
Up:
2.2.2 Declaring Enumerations
enum fruit {banana, apple, blueberry, mango} my_fruit;
enum fruit {banana, apple, blueberry, mango};
enum fruit my_fruit;
enum fruit {banana, apple, blueberry, mango};
banana = 15; /* You can't do this! */
Next: ,
Previous: ,
Up:
2.3 Unions
Next: ,
Up:
2.3.1 Defining Unions
union numbers
{
int i;
float f;
};
Next: ,
Previous: ,
Up:
2.3.2 Declaring Union Variables
Next: ,
Up:
union numbers
{
int i;
float f;
} first_number, second_number;
Next: ,
Previous: ,
Up:
union numbers
{
int i;
float f;
};
union numbers first_number, second_number;
Previous: ,
Up:
union numbers
{
int i;
float f;
};
union numbers first_number = { 5 };
union numbers first_number = { f: 3.14159 };
union numbers first_number = { .f = 3.14159 };
union numbers
{
int i;
float f;
} first_number = { 5 };
Next: ,
Previous: ,
Up:
2.3.3 Accessing Union Members
union numbers
{
int i;
float f;
};
union numbers first_number;
first_number.i = 5;
first_number.f = 3.9;
Previous: ,
Up:
2.3.4 Size of Unions
union numbers
{
int i;
float f;
};
Next: ,
Previous: ,
Up:
2.4 Structures
Next: ,
Up:
2.4.1 Defining Structures
struct point
{
int x, y;
};
Next: ,
Previous: ,
Up:
2.4.2 Declaring Structure Variables
Next: ,
Up:
struct point
{
int x, y;
} first_point, second_point;
Next: ,
Previous: ,
Up:
struct point
{
int x, y;
};
struct point first_point, second_point;
Previous: ,
Up:
struct point
{
int x, y;
};
struct point first_point = { 5, 10 };
struct point first_point = { .y = 10, .x = 5 };
struct point first_point = { y: 10, x: 5 };
struct point
{
int x, y;
} first_point = { 5, 10 };
struct pointy
{
int x, y;
char *p;
};
struct pointy first_pointy = { 5 };
struct point
{
int x, y;
};
struct rectangle
{
struct point top_left, bottom_right;
};
struct rectangle my_rectangle = { {0, 5}, {10, 0} };
Next: ,
Previous: ,
Up:
2.4.3 Accessing Structure Members
struct point
{
int x, y;
};
struct point first_point;
first_point.x = 0;
first_point.y = 5;
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: ,
Up:
2.4.4 Bit Fields
struct card
{
unsigned int suit : 2;
unsigned int face_value : 4;
};
Previous: ,
Up:
2.4.5 Size of Structures
Next: ,
Previous: ,
Up:
2.5 Arrays
Next: ,
Up:
2.5.1 Declaring Arrays
int my_array[10];
struct line
{
int length;
char contents[0];
};
{
struct line *this_line = (struct line *)
malloc (sizeof (struct line) + this_length);
this_line -> length = this_length;
}
int
my_function (int number)
{
int my_array[number];
...;
}
Next: ,
Previous: ,
Up:
2.5.2 Initializing Arrays
int my_array[5] = { 0, 1, 2, 3, 4 };
int my_array[5] = { 0, 1, 2 };
int my_array[5] = { [2] 5, [4] 9 };
int my_array[5] = { [2] = 5, [4] = 9 };
int my_array[5] = { 0, 0, 5, 0, 9 };
int new_array[100] = { [0 ... 9] = 1, [10 ... 98] = 2, 3 };
int my_array[] = { 0, 1, 2, 3, 4 };
int my_array[] = { 0, 1, 2, [99] = 99 };
Next: ,
Previous: ,
Up:
2.5.3 Accessing Array Elements
my_array[0] = 5;
struct point
{
int x, y;
};
struct point point_array[2] = { {4, 5}, {8, 9} };
point_array[0].x = 3;
Next: ,
Previous: ,
Up:
2.5.4 Multidimensional Arrays
int two_dimensions[2][5] { {1, 2, 3, 4, 5}, {6, 7, 8, 9, 10} };
two_dimensions[1][3] = 12;
Next: ,
Previous: ,
Up:
2.5.5 Arrays as Strings
char blue[26];
char yellow[26] = {'y', 'e', 'l', 'l', 'o', 'w', '\0'};
char orange[26] = "orange";
char gray[] = {'g', 'r', 'a', 'y', '\0'};
char salmon[] = "salmon";
char lemon[26] = "custard";
lemon = "steak sauce"; /* Fails! */
char name[] = "bob";
name[0] = 'r';
Next: ,
Previous: ,
Up:
2.5.6 Arrays of Unions
union numbers
{
int i;
float f;
};
union numbers number_array [3];
struct point point_array [3] = { {3}, {4}, {5} };
union numbers number_array [3];
number_array[0].i = 2;
Previous: ,
Up:
2.5.7 Arrays of Structures
struct point
{
int x, y;
};
struct point point_array [3];
struct point point_array [3] = { {2, 3}, {4, 5}, {6, 7} };
struct point point_array [3] = { {2}, {4, 5}, {6, 7} };
struct point point_array [3];
point_array[0].x = 2;
point_array[0].y = 3;
Next: ,
Previous: ,
Up:
2.6 Pointers
Next: ,
Up:
2.6.1 Declaring Pointers
data-type * name;
data-type *name;
data-type* name;
int *ip;
int *foo, *bar; /* Two pointers. */
int *baz, quux; /* A pointer and an integer variable. */
Next: ,
Previous: ,
Up:
2.6.2 Initializing Pointers
int i;
int *ip = &i;
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: ,
Up:
2.6.3 Pointers to Unions
union numbers
{
int i;
float f;
};
union numbers foo = {4};
union numbers *number_ptr = &foo;
number_ptr -> i = 450;
Previous: ,
Up:
2.6.4 Pointers to Structures
struct fish
{
float length, weight;
};
struct fish salmon = {4.3, 5.8};
struct fish *fish_ptr = &salmon;
fish_ptr -> length = 5.1;
fish_ptr -> weight = 6.2;
Next: ,
Previous: ,
Up:
2.7 Incomplete Types
struct point;
struct point
{
int x, y;
};
struct singly_linked_list
{
struct singly_linked_list *next;
int x;
/* other members here perhaps */
};
struct singly_linked_list *list_head;
Next: ,
Previous: ,
Up:
2.8 Type Qualifiers
const float pi = 3.14159f;
volatile float currentTemperature = 40.0;
Next: ,
Previous: ,
Up:
2.9 Storage Class Specifiers
void
foo (int value)
{
auto int x = value;
...
return;
}
int
sum (int x)
{
static int sumSoFar = 0;
sumSoFar = sumSoFar + x;
return sumSoFar;
}
extern int numberOfClients;
...
int numberOfClients = 0;
Previous: ,
Up:
2.10 Renaming Types
Next: ,
Previous: ,
Up:
3 Expressions and Operators
Next: ,
Up:
3.1 Expressions
47
2 + 2
cosine(3.14159) /* We presume this returns a floating point value. */
( 2 * ( ( 3 + 10 ) - ( 2 * 6 ) ) )
Next: ,
Previous: ,
Up:
3.2 Assignment Operators
int x = 10;
float y = 45.12 + 2.0;
int z = (2 * (3 + function () ));
struct foo {
int bar;
int baz;
} quux = {3, 4, 5};
x += y;
x = x + y;
Next: ,
Previous: ,
Up:
3.3 Incrementing and Decrementing
char w = '1';
int x = 5;
char y = 'B';
float z = 5.2;
int *p = &x;
++w; /* w is now the character `2' (not the value 2). */
x++; /* x is now 6. */
++y; /* y is now `C' (on ASCII systems). */
z++; /* z is now 6.2. */
++p; /* p is now &x + sizeof(int). */
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. */
5
7
int x = 5;
x--; /* x is now 4. */
Next: ,
Previous: ,
Up:
3.4 Arithmetic Operators
/* Addition. */
x = 5 + 3;
y = 10.23 + 37.332;
quux_pointer = foo_pointer + bar_pointer;
/* Subtraction. */
x = 5 - 3;
y = 57.223 - 10.903;
quux_pointer = foo_pointer - bar_pointer;
/* Multiplication. */
x = 5 * 3;
y = 47.4 * 1.001;
/* Division. */
x = 5 / 3;
y = 940.0 / 20.2;
/* Modular division. */
x = 5 % 3;
y = 74 % 47;
/* Negation. */
int x = -5;
float y = -3.14159;
#include
INT_MAX = 2147483647
INT_MIN = -2147483648
-INT_MIN = -2147483648
int x = +42;
Next: ,
Previous: ,
Up:
3.5 Complex Conjugation
__complex__ int x = 5 + 17i;
printf ("%d \n", (x * ~x));
Next: ,
Previous: ,
Up:
3.6 Comparison Operators
if (x == y)
puts (``x is equal to y'');
else
puts (``x is not equal to y'');
if (x != y)
puts (``x is not equal to y'');
else
puts (``x is equal to y'');
if (x < y)
puts (``x is less than y'');
if (x <= y)
puts (``x is less than or equal to y'');
if (x > y)
puts (``x is greater than y'');
if (x >= y)
puts (``x is greater than or equal to y'');
Next: ,
Previous: ,
Up:
3.7 Logical Operators
if ((x == 5) && (y == 10))
printf (``x is 5 and y is 10'');
if ((x == 5) || (y == 10))
printf (``x is 5 or y is 10'');
if (!(x == 5))
printf (``x is not 5'');
if (foo && x++)
bar();
Next: ,
Previous: ,
Up:
3.8 Bit Shifting
x = 47; /* 47 is 00101111 in binary. */
x << 1; /* 00101111 << 1 is 01011110. */
x = 47; /* 47 is 00101111 in binary. */
x >> 1; /* 00101111 >> 1 is 00010111. */
int d = 12;
int m = 6;
int y = 1983;
int x = ((y << 4) + m) << 5) + d;
d = x % 32;
m = (x >> 5) % 16;
y = x >> 9;
Next: ,
Previous: ,
Up:
3.9 Bitwise Logical Operators
11001001 & 10011011 = 10001001
11001001 | 10011011 = 11011011
11001001 ^ 10011011 = 01010000
~11001001 = 00110110
unsigned int foo = 42;
unsigned int bar = 57;
unsigned int quux;
quux = foo & bar;
quux = foo | bar;
quux = foo ^ bar;
quux = ~foo;
Next: ,
Previous: ,
Up:
3.10 Pointer Operators
int x = 5;
int *pointer_to_x = &x;
extern int foo (void);
int (*fp1) (void) = foo; /* fp1 points to foo */
int (*fp2) (void) = &foo; /* fp1 also points to foo */
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. */
Next: ,
Previous: ,
Up:
3.11 The sizeof Operator
size_t a = sizeof(int);
size_t b = sizeof(float);
size_t c = sizeof(5);
size_t d = sizeof(5.143);
size_t e = sizeof a;
#include
Next: ,
Previous: ,
Up:
3.12 Type Casts
float x;
int y = 7;
int z = 3;
x = (float) (y / z);
float x;
int y = 7;
int z = 3;
x = (y / (float)z);
struct fooTag { /* members ... */ };
struct fooTag foo;
unsigned char byteArray[8];
foo = (struct fooType) byteArray; /* Fail! */
Next: ,
Previous: ,
Up:
3.13 Array Subscripts
my_array[0] = 5;
Next: ,
Previous: ,
Up:
3.14 Function Calls as Expressions
int function(void);
...
a = 10 + function();
Next: ,
Previous: ,
Up:
3.15 The Comma Operator
x++, y = x * x;
/* Using the comma operator in a for statement. */
for (x = 1, y = 10; x <=10 && y >=1; x++, y--)
{
...
}
foo (x, y=47, x, z);
foo (x, (y=47, x), z);
Next: ,
Previous: ,
Up:
3.16 Member Access Expressions
struct point
{
int x, y;
};
struct point first_point;
first_point.x = 0;
first_point.y = 5;
struct fish
{
int length, weight;
};
struct fish salmon;
struct fish *fish_pointer = &salmon;
fish_pointer->length = 3;
fish_pointer->weight = 9;
Next: ,
Previous: ,
Up:
3.17 Conditional Expressions
a ? b : c
a = (x == 5) ? y : z;
if (x == 5)
a = y;
else
a = z;
Next: ,
Previous: ,
Up:
3.18 Statements and Declarations in Expressions
({ int y = function (); int z;
if (y > 0) z = y;
else z = - y;
z; })
#define max(a,b) ((a) > (b) ? (a) : (b))
#define maxint(a,b) \
({int _a = (a), _b = (b); _a > _b ? _a : _b; })
Next: ,
Previous: ,
Up:
3.19 Operator Precedence
expressions.
foo = *p++;
Previous: ,
Up:
3.20 Order of Evaluation
Next: ,
Up:
3.20.1 Side Effects
Next: ,
Previous: ,
Up:
3.20.2 Sequence Points
Next: ,
Previous: ,
Up:
3.20.3 Sequence Points Constrain Expressions
i = i + 1;
i = ++i + 1;
int x=0; bar((++x,++x))Allowed; the function bar takes one argument (the value 2
is passed here), and there is a sequence point at the comma operator.
*p++ || *p++Allowed; there is a sequence point at ||.
int x = 1, y = x++;Allowed; there is a sequence point after the full declarator of x.
x=2; x++;Allowed; there is a sequence point at the end of the first expression
statement.
if (x++ > MAX) x = 0;Allowed; there is a sequence point at the end of the controlling
expression of the if.
(x=y) ? ++x : x--;Allowed; there is a sequence point before the ?, and only one
of the two following expressions is evaluated.
int *p=malloc(sizeof(*p)), *q=p; *p=foo(); bar((*p)++,(*q)++);Not allowed; the object at p is being modified twice
before the evaluation of the arguments to bar is complete. The
fact that this is done once via p and once via q is
irrelevant, since they both point to the same object.
static int a = 1;
static int f (void)
{
a = 100;
return 3;
}
int foo (void)
{
return ++a * f();
}
The left operand ++a is evaluated firstFirst, a is incremented. Then the arguments to f are
evaluated (there are zero of them). Then there is a sequence point
before f is actually called.
Previous: ,
Up:
3.20.4 Sequence Points and Signal Delivery
Next: ,
Previous: ,
Up:
4 Statements
Next: ,
Up:
4.1 Labels
treet:
int treet = 5; /* treet the variable. */
treet: /* treet the label. */
Next: ,
Previous: ,
Up:
4.2 Expression Statements
5;
2 + 2;
10 >= 9;
x++;
y = x + 25;
puts ("Hello, user!");
*cucumber;
Next: ,
Previous: ,
Up:
4.3 The if Statement
if (test)
then-statement
else
else-statement
if (x == 10)
puts ("x is 10");
if (x == 10)
puts ("x is 10");
else
puts ("x is not 10");
if (x == 1)
puts ("x is 1");
else if (x == 2)
puts ("x is 2");
else if (x == 3)
puts ("x is 3");
else
puts ("x is something else");
void
easterDate (int y)
{
int n = 0;
int g = (y % 19) + 1;
int c = (y / 100) + 1;
int x = ((3 * c) / 4) - 12;
int z = (((8 * c) + 5) / 25) - 5;
int d = ((5 * y) / 4) - x - 10;
int e = ((11 * g) + 20 + z - x) % 30;
if (((e == 25) && (g > 11)) || (e == 24))
e++;
n = 44 - e;
if (n < 21)
n += 30;
n = n + 7 - ((d + n) % 7);
if (n > 31)
printf ("Easter: %d April %d", n - 31, y);
else
printf ("Easter: %d March %d", n, y);
}
Next: ,
Previous: ,
Up:
4.4 The switch Statement
switch (test)
{
case compare-1:
if-equal-statement-1
case compare-2:
if-equal-statement-2
...
default:
default-statement
}
switch (x)
{
case 0:
puts ("x is 0");
break;
case 1:
puts ("x is 1");
break;
default:
puts ("x is something else");
break;
}
int x = 0;
switch (x)
{
case 0:
puts ("x is 0");
case 1:
puts ("x is 1");
default:
puts ("x is something else");
}
x is 0
x is 1
x is something else
case low ... high:
case 'A' ... 'Z':
case 1 ... 5:
case 1...5:
Next: ,
Previous: ,
Up:
4.5 The while Statement
while (test)
statement
int counter = 0;
while (counter < 10)
printf ("%d ", counter++);
Next: ,
Previous: ,
Up:
4.6 The do Statement
do
statement
while (test);
int x = 0;
do
printf ("%d ", x++);
while (x < 10);
Next: ,
Previous: ,
Up:
4.7 The for Statement
for (initialize; test; step)
statement
int x;
for (x = 0; x < 10; x++)
printf ("%d ", x);
int x = 1;
for (; x <= 10; x++)
printf ("%d ", x);
for (x = 1; ; x++)
printf ("%d ", x);
for (x = 1; x <= 10;)
printf ("%d ", x);
int x, y;
for (x = 1, y = 10; x <= 10, y >= 1; x+=2, y--)
printf ("%d %d\n", x, y);
1 10
3 9
5 8
7 7
9 6
11 5
13 4
15 3
17 2
19 1
int x, y;
for (x = 1, y = 10; x <= 10 && y >= 1; x+=2, y--)
printf ("%d %d\n", x, y);
int
sum_of_squares (int start, int end)
{
int i, sum = 0;
for (i = start; i <= end; i++)
sum += i * i;
return sum;
}
Next: ,
Previous: ,
Up:
4.8 Blocks
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);
}
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);
}
}
{
int x = 5;
printf ("%d\n", x);
}
printf ("%d\n", x); /* Compilation error! x exists only
in the preceding block. */
Next: ,
Previous: ,
Up:
4.9 The Null Statement
;
for (i = 1; i*i < n; i++)
;
for (x = 1; x <= 5; printf ("x is now %d\n", x), x++)
;
Next: ,
Previous: ,
Up:
4.10 The goto Statement
goto label;
goto end_of_program;
...
end_of_program:
enum Play { ROCK=0, PAPER=1, SCISSORS=2 };
enum Result { WIN, LOSE, DRAW };
static enum Result turn (void)
{
const void * const jumptable[] = {&&rock, &&paper, &&scissors};
enum Play opp; /* opponent's play */
goto *jumptable[select_option (&opp)];
rock:
return opp == ROCK ? DRAW : (opp == PAPER ? LOSE : WIN);
paper:
return opp == ROCK ? WIN : (opp == PAPER ? DRAW : LOSE);
scissors:
return opp == ROCK ? LOSE : (opp == PAPER ? WIN : DRAW);
}
Next: ,
Previous: ,
Up:
4.11 The break Statement
int x;
for (x = 1; x <= 10; x++)
{
if (x == 8)
break;
else
printf ("%d ", x);
}
Next: ,
Previous: ,
Up:
4.12 The continue Statement
for (x = 0; x < 100; x++)
{
if (x % 2 == 0)
continue;
else
sum_of_odd_numbers + = x;
}
Next: ,
Previous: ,
Up:
4.13 The return Statement
return return-value;
x = cosine (y);
void
print_plus_five (int x)
{
printf ("%d ", x + 5);
return;
}
int
square_value (int x)
{
return x * x;
}
Previous: ,
Up:
4.14 The typedef Statement
typedef old-type-name new-type-name
typedef unsigned char byte_type;
typedef double real_number_type;
typedef struct fish
{
float weight;
float length;
float probability_of_being_caught;
} fish_type;
typedef char array_of_bytes [5];
array_of_bytes five_bytes = {0, 1, 2, 3, 4};
Next: ,
Previous: ,
Up:
5 Functions
Next: ,
Up:
5.1 Function Declarations
return-type function-name (parameter-list);
int foo (int, double);
int foo (int x, double y);
Next: ,
Previous: ,
Up:
5.2 Function Definitions
return-type
function-name (parameter-list)
{
function-body
}
int
add_values (int x, int y)
{
return x + y;
}
int
add_values (x, y)
int x, int y;
{
return x + y;
}
Next: ,
Previous: ,
Up:
5.3 Calling Functions
function-name (parameters)
foo (5);
a = square (5);
a = quux (5, 10);
Next: ,
Previous: ,
Up:
5.4 Function Parameters
int x = 23;
foo (x);
...
/* Definition for function foo. */
int foo (int a)
{
a = 2 * a;
return a;
}
x = foo (x);
void
foo (int *x)
{
*x = *x + 42;
}
...
int a = 15;
foo (&a);
struct foo
{
int x;
float y;
double z;
};
void bar (const struct foo *a);
void foo (int a[]);
...
int x[100];
foo (x);
void foo (int *a);
...
int x[100];
foo (x);
Next: ,
Previous: ,
Up:
5.5 Variable Length Parameter Lists
int add_multiple_values (int number, ...);
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;
}
sum = add_multiple_values (3, 12, 34, 190);
Next: ,
Previous: ,
Up:
5.6 Calling Functions Through Function Pointers
#include
Next: Recursive Functions,
Previous: ,
Up:
5.7 The main Function
int
main (void)
{
puts ("Hi there!");
return 0;
}
int
main (int argc, char *argv[])
{
int counter;
for (counter = 0; counter < argc; counter++)
printf ("%s\n", argv[counter]);
return 0;
}
5.8 Recursive Functions
int
factorial (int x)
{
if (x < 1)
return x;
else
return (x * factorial (x - 1));
}
int
watermelon (int x)
{
return (watermelon (x));
}
Next: ,
Previous: Recursive Functions,
Up:
5.9 Static Functions
static int
foo (int x)
{
return x + 42;
}
Previous: ,
Up:
5.10 Nested Functions
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);
}
Next: ,
Previous: ,
Up:
6 Program Structure and Scope
Next: ,
Up:
6.1 Program Structure
/* sqrt.h */
double
computeSqrt (double x);
/* sqrt.c */
#include "sqrt.h"
double
computeSqrt (double x)
{
double result;
...
return result;
}
Previous: ,
Up:
6.2 Scope
int x = 5;
int y = x + 10;
int x = y + 10;
int y = 5;
Next: ,
Previous: ,
Up:
7 A Sample Program
Next: ,
Up:
7.1 hello.c
/* hello.c -- print a greeting message and exit.
Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
2005, 2006, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include
Previous: ,
Up:
7.2 system.h
/* system.h: system-dependent declarations; include this first.
Copyright (C) 1996, 2005, 2006, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef HELLO_SYSTEM_H
#define HELLO_SYSTEM_H
/* Assume ANSI C89 headers are available. */
#include
Next: GNU Free Documentation License,
Previous: ,
Up:
Appendix A Overflow
Next: ,
Up:
A.1 Basics of Integer Overflow
Next: ,
Previous: ,
Up:
A.2 Examples of Code Assuming Wraparound Overflow