Sie sind auf Seite 1von 26

G

Introduction to C99

There is nothing like returning


to a place that remains
unchanged to find the ways in
which you yourself have altered.
Nelson Mandela

Everything you can imagine is


real.
Pablo Picasso

...life is too full of rich


possibilities to have restrictions
placed upon it.

Gloria Swanson

Objectives

In this appendix, youll learn:

Many of the new features of


the C99 standard.
To use // comments.
To mix declarations and
executable code and to
declare variables in for
statement headers.
To initialize arrays and
structs with designated
initializers.
To use data type bool to
create boolean variables
whose data values can be
true or false.
To manipulate variablelength arrays.
To perform arithmetic
operations on complex
variables.

2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

G.1 Introduction
G.1
G.2
G.3
G.4
G.5

Introduction
Support for C99
New C99 Headers
// Comments
Mixing Declarations and Executable
Code
G.6 Declaring a Variable in a for
Statement Header
G.7 Designated Initializers and
Compound Literals

LXXIX

G.8
G.9
G.10
G.11
G.12

Type bool
Implicit int in Function Declarations
Complex Numbers
Variable-Length Arrays
The snprintf Function: Helping
Avoid Hacker Attacks
G.13 Additions to the Preprocessor
G.14 Other C99 Features
G.15 Web Resources

Summary | Terminology | Self-Review Exercises | Answers to Self-Review Exercises | Exercises

G.1 Introduction
C99 is a revised standard for the C programming language that refines and expands the
capabilities of Standard C. C99 has not been widely adopted, and not all popular C compilers support it. Of the compilers that do offer C99 support, most support only a subset
of the language. For these reasons, we chose to discuss C99 only in this optional appendix.
Chapters 114 discuss C89 (the initial version of the ANSI/ISO standard), which is almost universally supported.
In this appendix, we provide an introduction to C99. We discuss compiler support
and include links to several free compilers and IDEs that provide various levels of C99 support. We explain with complete working code examples some of the key features of C99,
including // comments, mixing declarations and executable code, declarations in for
statements, designated initializers, compound literals, type bool, implicit int return type
in function prototypes and function definitions (not allowed in C99), complex numbers
and variable-length arrays. We provide brief explanations for additional key C99 features,
including extended identifiers, restricted pointers, reliable integer division, flexible array
members, the long long int type, generic math, inline functions, return without expression and function snprintf. Another significant feature is the addition of float and long
double versions of most of the math functions in <math.h>. We include an extensive list
of Internet and web resources to help you locate C99 compilers and IDEs, and dig deeper
into the technical details of the language.
The C standards committee is currently working on a new version of the standard,
known as C1x. Its likely to be finalized in 2012 or 2013. Few changes have been incorporated so far, but drafts of proposed changes are available on the committees website
(www.open-std.org/jtc1/sc22/wg14/).

G.2 Support for C99


Most C and C++ compilers did not support C99 when it was released. Support has grown
in recent years, and many compilers are close to being C99 compliant. The Microsoft Visual C++ 2008 Express Edition Software included with this book does not support C99.
For more information about this, visit blogs.msdn.com/vcblog/archive/2007/11/05/
iso-c-standard-update.aspx.
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

LXXX

Appendix G Introduction to C99

In this appendix, we run GNU GCC 4.3 on Linux, which supports most C99 features. To specify that the C99 standard should be used in compilation, you need to include
the command-line argument -std=c99 when you compile your programs. On Windows, you can install GCC to run C99 programs by downloading either Cygwin
(www.cygwin.com) or MinGW (sourceforge.net/projects/mingw). Cygwin is a complete Linux-style environment for Windows, while MinGW (Minimalist GNU for Windows) is a native Windows port of the compiler and related tools. Additionally, both GCC
and Microsoft Visual C++ can use the Dinkum C99 Standard Library from Dinkumware
(www.dinkumware.com/c99.aspx). This library provides all of the new required headers in
C99 and C95.

G.3 New C99 Headers


Figure G.1 lists alphabetically the standard library headers added in C99 (three of these
were added in C95).
Standard library
header

Explanation

<complex.h>

Contains macros and function prototypes for supporting complex numbers (see Section G.10). [C99 feature.]

<fenv.h>

Provides information about the C implementations floating-point environment and capabilities. [C99 feature.]
Defines several new portable integral types and provides format specifiers
for defined types. [C99 feature.]
Defines macros that represent the equality, relational and bitwise operators; an alternative to trigraphs. [C95 feature.]
Contains macros defining bool, true and false, used for boolean variables (see Section G.8). [C99 feature.]
Defines extended integer types and related macros. [C99 feature.]
Provides type-generic macros that allow functions from <math.h> to be
used with a variety of parameter types (see Section G.14). [C99 feature.]
Along with <wctype.h>, provides multibyte and wide-character input
and output support. [C95 feature.]
Along with <wchar.h>, provides wide-character library support. [C95
feature.]

<inttypes.h>
<iso646.h>
<stdbool.h>
<stdint.h>
<tgmath.h>
<wchar.h>
<wctype.h>

Fig. G.1 | Standard library headers added in C99 and C95.

G.4 // Comments
[Note: This section can be taught after Section 2.2.]
C99 allows you to use // comments (as C++, Java, and C# do). Whenever the characters
// appear outside quotation marks, the rest of the line is treated as a comment (see
Fig. G.2lines 1, 2, 7, 10, 12 and 13).
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

G.5 Mixing Declarations and Executable Code

LXXXI

G.5 Mixing Declarations and Executable Code


[Note: This section can be taught after Section 2.3.]
C89 requires that all variables with block scope be declared at the start of a block. C99
allows mixing declarations and executable code. A variable can be declared anywhere in
a block prior to usage. Consider the C99 program of Fig. G.2.
1
2
3
4
5
6
7
8
9
10
11
12
13

// Fig. G.2: figG_02.c


// Mixing declarations and executable code in C99
#include <stdio.h>
int main( void )
{
int x = 1; // declare variable at beginning of block
printf( "x is %d\n", x );
int y = 2; // declare variable in middle of executable code
printf( "y is %d\n", y );
return 0; // indicates successful termination
} // end main

x is 1
y is 2

Fig. G.2 | Mixing declarations and executable code in C99.


In this program, we call printf (executable code) in line 8, yet declare the int variable
in line 10. This is not allowed in C89. In C99 you can declare variables close to their
first use, even if those declarations appear after executable code in a block. We dont
declare int y (line 10) until just before we use it (line 11). Although this can improve program readability and reduce the possibility of unintended references, many programmers
still prefer to group their variable declarations together at the beginnings of blocks.
A variable cannot be declared after code that uses the variable. In Fig. G.3 we declare
int y (line 12) after an executable statement that attempts to print y (line 10). This results
in a compilation error.
y

1
2
3
4
5
6
7
8
9
10
11

// Fig. G.3: figG_03.c


// Attempting to declare a variable after its use in C99
#include <stdio.h>
int main( void )
{
int x = 1; // declare x
printf( "The value of x is %d\n", x ); // output x
printf( "The value of y is %d\n", y ); // output y (error)

Fig. G.3 | Attempting to declare a variable after its use in C99. [Error produced by GCC 4.3] (Part
1 of 2.)
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

LXXXII
12
13
14

Appendix G Introduction to C99

int y = 2; // declare y
return 0; // indicates successful termination
} // end main

figG_03.c: In
figG_03.c:10:
figG_03.c:10:
figG_03.c:10:

function main:
error: y undeclared (first use in this function)
error: (Each undeclared identifier is reported only once
error: for each function it appears in.)

Fig. G.3 | Attempting to declare a variable after its use in C99. [Error produced by GCC 4.3] (Part
2 of 2.)

G.6 Declaring a Variable in a for Statement Header


[Note: This section can be taught after Section 4.4.]
As you may recall, a for statement consists of an initialization, a loop-continuation condition, an increment, and a loop body. Figure G.4 shows a C89 program that uses a for
statement to output the numbers 1 through 5.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

/* Fig. G.4: figG_04.c


Declaring a loop counter before a for statement in C89 */
#include <stdio.h>
int main( void )
{
int x; /* declare loop counter */
/* output values 1 through 5 */
printf( "Values of x\n" );
for ( x = 1; x <= 5; x++ ) { /* initialize loop counter */
printf( "%d\n", x );
} /* end for */
printf( "Value of x is %d\n", x ); /* x is still in scope */
return 0; /* indicates successful termination */
} /* end main */

Values of x
1
2
3
4
5
Value of x is 6

Fig. G.4 | Declaring a loop counter before a for statement in C89.


C99 expands on the C89 definition of the for statement, allowing the initialization
clause to include a declaration. Rather than using an existing variable as a loop counter,
we can create a new loop-counter variable in the for statement header whose scope is lim 2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

G.6 Declaring a Variable in a for Statement Header

LXXXIII

ited to the for statement. The C99 program of Fig. G.5 declares a variable in a for statement header.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

// Fig. G.5: figG_05.c


// Declaring a variable in a for statement header in C99
#include <stdio.h>
int main( void )
{
printf( "Values of x\n" );
// declare a variable in a for statement header
for ( int x = 1; x <= 5; x++ ) {
printf( "%d\n", x );
} // end for
return 0; // indicates successful termination
} // end main

Values of x
1
2
3
4
5

Fig. G.5 | Declaring a variable in a for statement header in C99.


Any variable declared in a for statement has the scope of the for statementthe variable does not exist outside the for statement. Figure G.6 shows a failed attempt to access
such a variable after the statement body.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

// Fig. G.6: figG_06.c


// Accessing a for statement variable after the for statement in C99
#include <stdio.h>
int main( void )
{
printf( "Values of x:\n" );
// declare variable in for statement header
for ( int x = 1; x <= 5; x++ ) {
printf( "%d\n", x );
} // end for
printf( "Value of x is: %d\n", x ); // x is out of scope
return 0; // indicates successful termination
} // end main

Fig. G.6 | Accessing a for statement variable after the for statement in C99. [Error produced
by GCC 4.3] (Part 1 of 2.)
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

LXXXIV

figG_06.c: In
figG_06.c:14:
figG_06.c:14:
figG_06.c:14:

Appendix G Introduction to C99

function main:
error: x undeclared (first use in this function)
error: (Each undeclared identifier is reported only once
error: for each function it appears in.)

Fig. G.6 | Accessing a for statement variable after the for statement in C99. [Error produced
by GCC 4.3] (Part 2 of 2.)

G.7 Designated Initializers and Compound Literals


[Note: This section can be taught after Section 10.3.]
Designated initializers allow you to initialize the elements of an array, union or struct
explicitly by subscript or name. Figure G.7 shows how we might assign the first and last
elements of an array in C89.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

/* Fig. G.7: figG_07.c


Assigning elements of an array in C89 */
#include <stdio.h>
int main( void )
{
int i; /* declare loop counter */
int a[ 5 ]; /* array declaration */
a[ 0 ] = 1; /* explicitly assign values to array elements... */
a[ 4 ] = 2; /* after the declaration of the array */
/* assign zero to all elements but the first and last */
for ( i = 1; i < 4; i++ ) {
a[ i ] = 0;
} /* end for */
/* output array contents */
printf( "The array is\n" );
for ( i = 0; i < 5; i++ ) {
printf( "%d\n", a[ i ] );
} /* end for */
return 0; /* indicates successful termination */
} /* end main */

The array is
1
0
0
0
2

Fig. G.7 | Assigning elements of an array in C89.


2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

G.7 Designated Initializers and Compound Literals

LXXXV

In Fig. G.8 we show the program again, but rather than assigning values to the first
and last elements of the array, we initialize them explicitly by subscript, using designated
initializers.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

// Fig. G.8: figG_08.c


// Using designated initializers
// to initialize the elements of an array in C99
#include <stdio.h>
int main( void )
{
int a[ 5 ] =
{
[ 0 ] = 1, // initialize elements with designated initializers...
[ 4 ] = 2 // within the declaration of the array
}; // semicolon is required
// output array contents
printf( "The array is \n" );
for ( int i = 0; i < 5; i++ ) {
printf( "%d\n", a[ i ] );
} // end for
return 0; // indicates successful termination
} // end main

The array is
1
0
0
0
2

Fig. G.8 | Using designated initializers to initialize the elements of an array in C99.
Lines 812 declare the array and initialize the specified elements within the braces.
Note the syntax. Each initializer in the initializer list (lines 1011) is separated from the
next by a comma, and the end brace is followed by a semicolon. Elements that are not
explicitly initialized are implicitly initialized to zero (of the correct type). This syntax is not
allowed in C89.
In addition to using an initializer list to declare a variable, you can also use an initializer list to create an unnamed array, struct or union. This is known as a compound literal. For example, if you want to pass an array equivalent to a in Fig. G.8 to a function
without having to declare it beforehand, you could use
demoFunction( ( int [ 5 ] ) { [ 0 ] = 1, [ 4 ] = 2 } );

Consider the more elaborate example in Fig. G.9, where we use designated initializers
for an array of structs.
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

LXXXVI
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
x
1
0
0
0
10

Appendix G Introduction to C99

// Fig. G.9: figG_09.c


// Using designated initializers to initialize an array of structs in C99
#include <stdio.h>
struct twoInt // declare a struct of two integers
{
int x;
int y;
}; // end struct twoInt
int main( void )
{
// explicitly initialize elements of array a
// then explicitly initialize members of each struct element
struct twoInt a[ 5 ] =
{
[ 0 ] = { .x = 1, .y = 2 },
[ 4 ] = { .x = 10, .y = 20 }
};
// output array contents
printf( "x\ty\n" );
for ( int i = 0; i < 5; i++ ) {
printf( "%d\t%d\n", a[ i ].x, a[ i ].y );
} // end for
return 0; // indicates successful termination
} //end main
y
2
0
0
0
20

Fig. G.9 | Using designated initializers to initialize an array of structs in C99.


Line 17 uses a designated initializer to explicitly initialize a struct element of the
array. Then, within that initialization, we use another level of designated initializer, explicitly initializing the x and y members of the struct. To initialize struct or union members
we list each members name preceded by a period.
Compare lines 1519 of Fig. G.9, which use designated initializers to the following
executable code, which does not use designated initializers:
struct twoInt a[ 5 ];
a[
a[
a[
a[

0
0
4
4

].x
].y
].x
].y

=
=
=
=

1;
2;
10;
20;

2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

G.8 Type bool

LXXXVII

G.8 Type bool


[Note: This section can be taught after Section 3.6.]
The C99 boolean type is _Bool, which can hold only the values 0 or 1. Recall Cs convention of using zero and nonzero values to represent false and truethe value 0 in a condition evaluates to false, while any nonzero value in a condition evaluates to true. Assigning
any non-zero value to a _Bool sets it to 1. C99 provides the <stdbool.h> header file which
defines macros representing the type bool and its values (true and false). These macros
replace true with 1, false with 0 and bool with the C99 keyword _Bool. Figure G.10
uses a function named isEven (lines 3341) that returns a bool value indicating whether
a number input by the user is odd or even.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

// Fig. G.10: figG_10.c


// Using the boolean type and the values true and false in C99.
#include <stdio.h>
#include <stdbool.h> // allows the use of bool, true, and false
bool isEven( int number ); // function prototype
int main( void )
{
// loop for 2 inputs
for ( int i = 0; i < 2; i++ ) {
int input; // value entered by user
printf( "Enter an integer: " );
scanf( "%d", &input );
bool valueIsEven = isEven( input ); // determine if input is even
// determine whether input is even
if ( valueIsEven ) {
printf( "%d is even \n\n", input );
} // end if
else {
printf( "%d is odd \n\n", input );
} // end else
} // end for
return 0;
} // end main
// even returns true if number is even
bool isEven( int number )
{
if ( number % 2 == 0 ) { // is number divisible by 2?
return true;
}
else {
return false;
}
} // end function isEven

Fig. G.10 | Using the type bool and the values true and false in C99. (Part 1 of 2.)
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

LXXXVIII

Appendix G Introduction to C99

Enter an integer: 34
34 is even
Enter an integer: 23
23 is odd

Fig. G.10 | Using the type bool and the values true and false in C99. (Part 2 of 2.)
Line 11 declares a bool variable named valueIsEven. Lines 1516 in the loop prompt
the user to enter an integer and input the integer. Line 18 passes the input to function
isEven (lines 3341). Function isEven returns a value of type bool. Line 35 uses the
remainder operator to determine whether the argument is divisible by 2. If so, line 36
returns true (i.e., the number is even); otherwise, line 39 returns false (i.e., the number
is odd). The result is assigned to bool variable valueIsEven in line 18. Line 21 uses this
variable as the condition in an ifelse statement. If valueIsEven is true, line 22 displays a string indicating that the value is even. If valueIsEven is false, line 25 displays a
string indicating that the value is odd.

G.9 Implicit int in Function Declarations


[Note: This section can be taught after Section 5.5.]
In C89, if a function does not have an explicit return type, it implicitly returns an int. In
addition, if a function does not have a specified parameter type, it declares it as int. Consider the program in Fig. G.11.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

/* Fig. G.11: figG_11.c


Using implicit int in C89 */
#include <stdio.h>
returnImplicitInt(); /* prototype with unspecified return type */
int demoImplicitInt( x ); /* prototype with unspecified parameter type */
int main( void )
{
int x;
int y;
/* assign data of unspecified return type to int */
x = returnImplicitInt();
/* pass in an int to a function with an unspecified type */
y = demoImplicitInt( 82 );
printf( "x is %d\n", x );
printf( "y is %d\n", y );
return 0; /* indicates successful termination */
} /* end main */

Fig. G.11 | Using implicit int in C89. (Part 1 of 2.)


2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

G.10 Complex Numbers


24
25
26
27
28
29
30
31
32

LXXXIX

returnImplicitInt()
{
return 77; /* returning an int when return type is not specified */
} /* end function returnImplicitInt */
int demoImplicitInt( x )
{
return x;
} /* end function demoImplicitInt */

Fig. G.11 | Using implicit int in C89. (Part 2 of 2.)


When this program is run in Microsofts Visual C++ 2008 Express Edition, which is
not C99 compliant, no compilation errors or warning messages occur and the program
executes correctly. C99 disallows the use of the implicit int, requiring that C99-compliant
compilers issue either a warning or an error. When we run the same program using GCC
4.3, which is mostly C99 compliant, we get the warning messages shown in Fig. G.12.
figG_11.c:5: warning: data definition has no type or storage class
figG_11.c:5: warning: type defaults to int in declaration
of returnImplicitInt
figG_11.c:6: warning: parameter names (without types) in function declaration
figG_11.c:25: warning: return type defaults to int
figG_11.c: In function demoImplicitInt:
figG_11.c:30: warning: type of x defaults to int

Fig. G.12 | Warning messages for implicit int produced by GCC 4.3.
Although the program still executes, it is important that you heed the warning messages and abstain from using any implicit int function. Some compilers treat implicit int
functions as compilation errors, preventing the program from executing.

G.10 Complex Numbers


[Note: This section can be taught after Section 5.3.]
The C99 standard introduces support for complex numbers and complex arithmetic. The
program of Fig. G.13 performs basic operations with complex numbers.
1
2
3
4
5
6
7
8
9
10

// Fig. G.13: figG_13.c


// Using complex numbers in C99
#include <stdio.h>
#include <complex.h> // for complex type and math functions
int main( void )
{
double complex a = 32.123 + 24.456 * I; // a is 32.123 + 24.456i
double complex b = 23.789 + 42.987 * I; // b is 23.789 + 42.987i
double complex c = 3.0 + 2.0 * I;

Fig. G.13 | Using complex numbers in C99. (Part 1 of 2.)


2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

XC
11
12
13
14
15
16
17
18
19
20
21
22
23
a
b
a
a
a
a
a

Appendix G Introduction to C99

double complex sum = a + b; // perform complex addition


double complex pwr = cpow( a, c ); // perform complex exponentiation
printf( "a is %f + %fi\n", creal( a ), cimag( a ));
printf( "b is %f + %fi\n", creal( b ), cimag( b ));
printf( "a + b is: %f + %fi\n", creal( sum ), cimag( sum
printf( "a - b is: %f + %fi\n", creal( a - b ), cimag( a
printf( "a * b is: %f + %fi\n", creal( a * b ), cimag( a
printf( "a / b is: %f + %fi\n", creal( a / b ), cimag( a
printf( "a ^ b is: %f + %fi\n", creal( pwr ), cimag( pwr
return 0; // indicates successful termination
} // end main

));
- b ));
* b ));
/ b ));
));

is 32.123000 + 24.456000i
is 23.789000 + 42.987000i
+ b is: 55.912000 + 67.443000i
- b is: 8.334000 + -18.531000i
* b is: -287.116025 + 1962.655185i
/ b is: 0.752119 + -0.331050i
^ b is: -17857.051995 + 1365.613958i

Fig. G.13 | Using complex numbers in C99. (Part 2 of 2.)


For C99 to recognize complex, we include the <complex.h> header (line 4). This will
expand the macro complex to the keyword _Complexa type that reserves an array of
exactly two elements, corresponding to the complex numbers real part and imaginary
part.
Having included the header file in line 4, we can define variables as in lines 810 and
1213. We define each of the variables a, b, c, sum and pwr as type double complex. We
could also have used float complex, or long double complex.
The arithmetic operators work with complex numbers. The <complex.h> header also
defines several math functions, for example, cpow in line 13. [Note: You can also use the
operators !, ++, --, &&, ||, ==, != and unary & with complex numbers.]
Lines 1721 output the results of various arithmetic operations. The real part and the
imaginary part of a complex number can be accessed with functions creal and cimag,
respectively, as shown in lines 1521. In the output string of line 21, we use the symbol ^
to indicate exponentiation.

G.11 Variable-Length Arrays


[Note: This section can be taught after Section 6.9.]
In C89, arrays are of constant size. But what if you dont know an arrays size at compilation time? To handle this, youd have to use dynamic memory allocation with malloc and
related functions. C99 allows you to handle arrays of unknown size using variable-length
arrays (VLAs). These are not arrays whose size can changethat would compromise the
integrity of nearby locations in memory. A variable-length array is an array whose length,
or size, is defined in terms of an expression evaluated at execution time. The program of
Fig. G.14 declares and prints several VLAs.
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

G.11 Variable-Length Arrays


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

XCI

// Fig. G.14: figG_14.c


// Using variable-length arrays in C99
#include <stdio.h>
// function prototypes
void print1DArray( int size, int arr[ size ] );
void print2DArray( int row, int col, int arr[ row ][ col ] );
int main( void )
{
int arraySize; // size of 1-D array
int row1, col1, row2, col2; // number of rows and columns in 2-D arrays
printf( "Enter size of a one-dimensional array: " );
scanf( "%d", &arraySize );
printf( "Enter number of rows and columns in a 2-D array: " );
scanf( "%d %d", &row1, &col1 );
printf( "Enter number of rows and columns in another 2-D array: " );
scanf( "%d %d", &row2, &col2 );
int array[ arraySize ]; // declare 1-D variable-length array
int array2D1[ row1 ][ col1 ]; // declare 2-D variable-length array
int array2D2[ row2 ][ col2 ]; // declare 2-D variable-length array
// test sizeof operator on VLA
printf( "\nsizeof(array) yields array size of %d bytes\n",
sizeof( array ) );
// assign elements of 1-D VLA
for ( int i = 0; i < arraySize; i++ ) {
array[ i ] = i * i;
} // end for
// assign elements of first 2-D VLA
for ( int i = 0; i < row1; i++ ) {
for ( int j = 0; j < col1; j++ ) {
array2D1[ i ][ j ] = i + j;
} // end for
} // end for
// assign elements of second 2-D VLA
for ( int i = 0; i < row2; i++ ) {
for ( int j = 0; j < col2; j++ ) {
array2D2[ i ][ j ] = i + j;
} // end for
} // end for
printf( "\nOne-dimensional array:\n" );
print1DArray( arraySize, array ); // pass 1-D VLA to function

Fig. G.14 | Using variable-length arrays in C99. (Part 1 of 2.)


2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

XCII
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

Appendix G Introduction to C99

printf( "\nFirst two-dimensional array:\n" );


print2DArray( row1, col1, array2D1 ); // pass 2-D VLA to function
printf( "\nSecond two-dimensional array:\n" );
print2DArray( row2, col2, array2D2 ); // pass other 2-D VLA to function
return 0; // indicates successful termination
} // end main
void print1DArray( int size, int array[ size ] )
{
// output contents of array
for ( int i = 0; i < size; i++ ) {
printf( "array[%d] = %d\n", i, array[ i ] );
} // end for
} // end function print1DArray
void print2DArray( int row, int col, int arr[ row ][ col ] )
{
// output contents of array
for ( int i = 0; i < row; i++ ) {
for ( int j = 0; j < col; j++ ) {
printf( "%5d", arr[ i ][ j ] );
} // end for
printf( "\n" );
} // end for
} // end function print2DArray

Enter size of a one-dimensional array: 6


Enter number of rows and columns in a 2-D array: 2 5
Enter number of rows and columns in another 2-D array: 4 3
sizeof(array) yields array size of 24 bytes
One-dimensional array:
array[0] = 0
array[1] = 1
array[2] = 4
array[3] = 9
array[4] = 16
array[5] = 25
First two-dimensional array:
0
1
2
3
4
1
2
3
4
5
Second two-dimensional array:
0
1
2
1
2
3
2
3
4
3
4
5

Fig. G.14 | Using variable-length arrays in C99. (Part 2 of 2.)


First, we prompt the user for the desired sizes for a one-dimensional array and two
two-dimensional arrays (lines 1421). Lines 2325 then declare VLAs of the appropriate
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

G.12 The snprintf Function: Helping Avoid Hacker Attacks

XCIII

size. This leads to a compilation error in C89 but is valid in C99, as long as the variables
representing the array sizes are of an integral type.
After declaring the arrays, we use the sizeof operator in lines 2829 to make sure that
our VLA is of the proper length. In C89 sizeof is always a compile-time operation, but
when applied to a VLA in C99, sizeof operates at runtime. The output window shows
that the sizeof operator returns a size of 24 bytesfour times that of the number we
entered because the size of an int on our machine is 4 bytes.
Next we assign values to the elements of our VLAs (lines 3248). We use i < arraySize as our loop-continuation condition when filling the one-dimensional array. As with
fixed-length arrays, there is no protection against stepping outside the array bounds.
Lines 6167 define function print1DArray that takes a one-dimensional VLA. The
syntax for passing VLAs as parameters to functions is the same as with a normal, fixedlength array. We use the variable size in the declaration of the array parameter, but no
checking is performed other than the variable being defined and of integral typeit is
purely documentation for the programmer.
Function print2DArray (lines 6979) takes a variable-length two-dimensional array
and displays it to the screen. Recall from Section 6.9 that in C89, all but the first subscript
of a multi-dimensional array must be specified when declaring a function parameter. The
same restriction holds true for C99, except the sizes can be specified by variables. The initial value of col passed to the function is used to convert from two-dimensional indices to
offsets into the contiguous memory the array is stored in, just as with a fixed-size array.
Changing the value of col inside the function will not cause any changes to the indexing,
but passing an incorrect value to the function will.

G.12 The snprintf Function: Helping Avoid Hacker


Attacks
[Note: This section can be taught after Section 8.5.]
The snprintf function is new in C99 and is broadly supported, even among vendors who
do not claim to be C99-compliant. It helps prevent buffer overflows, a popular form of
hacker attack. The sprintf and snprintf prototypes are:
int sprintf( char * restrict s, const char * restrict format, ... );
int snprintf( char * restrict s, size_t n,
const char * restrict format, ... );

The old sprintf function writes into a buffer but does not know how big the buffer
is. It simply writes as much as necessary, which may destroy anything located after the
buffer in memory. We covered sprintf in the table of Fig. 8.12 and the code example of
Fig. 8.13.
Figure G.15 uses snprintf to read two numbers from the user (lines 1516) and display them. The initial call of snprintf (line 19) is used to determine how much memory
is needed to hold the formatted string. The snprintf function returns the number of characters that would have been stored in the destination array if it was large enough, not
counting the terminating null character. This length is increased by one to allow for the
null character and used to allocate a variable-length array of the correct size.
Once an array of the correct size is created, line 25 calls snprintf again to actually
format the output. The resulting return value, length of string, and formatted string are
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

XCIV
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Appendix G Introduction to C99

// Fig. G.15: figG_15.c


// Using snprintf to print to a string safely
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ensure the same format string is used for both calls
#define DISPLAY_FORMAT "integer: %d\tfloat: %.2f"
int main( void )
{
int x; // integer to be input
float y; // float to be input
printf( "Enter an integer and a float:\n" );
scanf( "%d %f", &x, &y );
// call snprintf to determine how much space we need
int length = snprintf( NULL, 0, DISPLAY_FORMAT, x, y );
int size = length + 1; // add one byte for terminating null character
printf( "Creating a buffer of size: %d\n\n", size );
char string[ size ]; // create VLA to print into
// call with buffer to store formatted string
length = snprintf( string, size, DISPLAY_FORMAT, x, y );
// display results
printf( "Return value: %d\n", length );
printf( "String length: %d\n", ( int ) strlen( string ) );
printf( "Formatted string:\n%s\n", string );
return 0; // indicates successful termination
} // end main

Enter an integer and a float:


457 97.12
Creating a buffer of size: 26
Return value: 25
String length: 25
Formatted string:
integer: 457
float: 97.12

Fig. G.15 | Using snprintf to print to a string safely.


displayed (lines 2830). The return value and string length are equalthis means that
there was no truncation due to the buffer being too small.
With snprintf, the size of the buffer is passed into the function, which will not write
past the end of the buffer. This maintains the integrity of data in memory even if there is
a logic error or buffer size error in the program. By avoiding buffer overflows, snprintf
makes programs easier to debug because a buffer overflow can make unrelated parts of the
program fail, making it difficult to identify the real problem. [For more information, see
C99 Standard Section 7.19.6.5.]
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

G.13 Additions to the Preprocessor

XCV

G.13 Additions to the Preprocessor


[Note: This section can be taught after Chapter 13.]
C99 adds additional features to the C preprocessor. The first addition is the _Pragma operator, which functions like the #pragma directive introduced in Section 13.6. _Pragma
( "tokens" ) has the same effect as #pragma tokens, but is more flexible because it can be
used inside a macro definition. Therefore, instead of surrounding each usage of a compiler-specific pragma by an #if directive, you can simply define a macro using the _Pragma
operator once and use it anywhere in your program.
Second, C99 specifies three standard pragmas that deal with the behavior of floatingpoint operations. The first token in these standard pragmas is always STDC, the second is
one of FENV_ACCESS, FP_CONTRACT or CX_LIMITED_RANGE, and the third is ON, OFF or
DEFAULT to indicate whether the given pragma should be enabled, disabled, or set to its
default value, respectively. The FENV_ACCESS pragma is used to inform the compiler which
portions of code will use functions in the C99 <fenv.h> header. On modern desktop systems, floating-point processing is done with 80-bit floating-point values. If FP_CONTRACT
is enabled, the compiler may perform a sequence of operations at this precision and store
the final result into a lower-precision float or double instead of reducing the precision
after each operation. Finally, if CX_LIMITED_RANGE is enabled, the compiler is allowed to
use the standard mathematical formulas for complex operations such as multiplying or
dividing. Because floating-point numbers are not stored exactly, using the normal mathematical definitions can result in overflows where the numbers get larger than the floatingpoint type can represent, even if the operands and result are below this limit.
Third, the C99 preprocessor allows passing empty arguments to a macro callin the
previous version, the behavior of an empty argument was undefined, though GCC acts
according to the C99 standard even in C89 mode. In many cases, it results in a syntax error,
but in some cases it can be useful. For instance, consider a macro PTR(type, cv, name)
defined to be type * cv name. In some cases, there is no const or volatile declaration on
the pointer, so the second argument will be empty. When an empty macro argument is used
with the # or ## operator (Section 13.7), the result is the empty string or the identifier the
argument was concatenated with, respectively.
A key preprocessor addition is variable-length argument lists for macros. This allows
for macro wrappers around functions like printffor example, to automatically add the
name of the current file to a debug statement, you can define a macro as follows:
#define DEBUG( ... ) printf( __FILE__ ": " __VA_ARGS__ )

The DEBUG macro takes a variable number of arguments, as indicated by the ... in the argument list. As with functions, the ... must be the last argument; unlike functions, it may
be the only argument. The identifier __VA_ARGS__, which begins and ends with two underscores, is a placeholder for the variable-length argument list. When a call such as
DEBUG( "x = %d, y = %d\n", x, y );

is preprocessed, it is replaced with


printf( "file.c" ": " "x = %d, y = %d\n", x, y );

As mentioned in Section 13.7, strings separated by white space are concatenated during preprocessing, so the three string literals will be combined to form the first argument to printf.
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

XCVI

Appendix G Introduction to C99

G.14 Other C99 Features


Here we provide brief overviews of some additional key new features of C99.

Compiler Minimum Resource Limits


[Note: This section can be taught after Section 14.5.]
C89 requires implementations of the language to support identifiers of no less than 31
characters for identifiers with internal linkage (valid only within the file being compiled)
and no less than six characters for identifiers with external linkage (also valid in other files).
For more information on internal and external linkage, see Section 14.5. The C99 standard increases these limits to 63 characters for identifiers with internal linkage and to 31
characters for identifiers with external linkage. These are just lower limits. Compilers are
free to support identifiers with more characters than these limits. Identifiers are now allowed to contain national language characters via Universal Character Names (C99 Standard, Section 6.4.3) and, if the implementation chooses, directly (C99 Standard, Section
6.4.2.1). [For more information, see C99 Standard Section 5.2.4.1.]
In addition to increasing the identifier length compilers are required to support, the
C99 standard sets minimum limits on many language features. For example, compilers are
required to support at least 1023 members in a struct, enum or union, and at least 127
parameters to a function. For more information on other limits set by the C99 Standard,
see C99 Standard Section 5.2.4.1.
The restrict Keyword
[Note: This section can be taught after Section 7.5.]
The keyword restrict is used to declare restricted pointers. We declare a restricted
pointer when that pointer should have exclusive access to a region of memory. Objects accessed through a restricted pointer cannot be accessed by other pointers except when the
value of those pointers was derived from the value of the restricted pointer. We can declare
a restricted pointer to an int as:
int *restrict ptr;

Restricted pointers allow the compiler to optimize the way the program accesses memory.
For example, the standard library function memcpy is defined in the C99 standard as follows:
void *memcpy( void *restrict s1, const void *restrict s2, size_t n );

The specification of the memcpy function states that it cannot be used to copy between
overlapping regions of memory. Using restricted pointers allows the compiler to see that
requirement, and it can optimize the copy by copying multiple bytes at a time, which is
more efficient. Incorrectly declaring a pointer as restricted when another pointer points to
the same region of memory can result in undefined behavior. [For more information, see
C99 Standard Section 6.7.3.1.]

Reliable Integer Division


[Note: This section can be taught after Section 2.5.]
In C89, the behavior of integer division varies across implementations. Some implementations round a negative quotient toward negative infinity, while others round toward zero. When one of the integer operands is negative, this can result in different answers.
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

G.14 Other C99 Features

XCVII

Consider dividing 28 by 5. The exact answer is 5.6. If we round the quotient toward
zero, we get the integer result of 5. If we round 5.6 toward negative infinity, we get an
integer result of 6. C99 removes the ambiguity and always performs integer division (and
integer modulus) by rounding the quotient toward zero. This makes integer division reliableC99-compliant platforms all treat integer division in the same way. [For more information, see C99 Standard Section 6.5.5.]

Flexible Array Members


[Note: This section can be taught after Section 10.3.]
C99 allows us to declare an array of unspecified length as the last member of a struct.
Consider the following
struct s {
int arraySize;
int array[];
}; // end struct s

A flexible array member is declared by specifying empty square brackets ([]). To allocate
a struct with a flexible array member, use code such as
int desiredSize = 5;
struct s *ptr;
ptr = malloc( sizeof( struct s ) + sizeof( int ) * desiredSize );

The sizeof operator ignores flexible array members. The sizeof( struct s ) phrase is
evaluated as the size of all the members in a struct s except for the flexible array. The
extra space we allocate with sizeof( int ) * desiredSize is the size of our flexible array.
There are many restrictions on the use of flexible array members. A flexible array
member can be declared only as the last member of a structeach struct can contain
at most one flexible array member. Also, a flexible array cannot be the only member of a
struct. The struct must also have one or more fixed members. Furthermore, any struct
containing a flexible array member cannot be a member of another struct. Finally, a
struct with a flexible array member cannot be statically initializedit must be allocated
dynamically. You cannot fix the size of the flexible array member at compile time. [For
more information, see C99 Standard Section 6.7.2.1.]

Relaxed Constraints on Aggregate Initialization


[Note: This section can be taught after Section 10.3.]
In C99, it is no longer required that aggregates such as arrays, structs, and unions be initialized by constant expressions. This enables the use of more concise initializer lists instead of using many separate statements to initialize members of an aggregate.
Type
[Note: This section can be taught after Section 4.7.]
C99 introduces the type long long int, which is guaranteed to be at least 64 bits long.
Systems without 64-bit hardware must emulate it in software. It is never equivalent to
long (even if it is the same size, it is still a separate and distinct type). C99 introduces functions such as atoll for converting strings to long long int and the length modifier ll (for
long long) that can precede any of the integer conversion specifiers listed in Fig. 9.1
(e.g., %lld). [For more information, see C99 Standard Section 6.2.5.]
long long int

2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

XCVIII

Appendix G Introduction to C99

Type Generic Math


[Note: This section can be taught after Section 5.3.]
The <tgmath.h> header is new in C99. It provides type-generic macros for many math
functions in <math.h>. For example, after including <tgmath.h>, if x is a float, the expression sin(x) will call sinf (the float version of sin); if x is a double, sin(x) will call
sin (which takes a double argument); if x is a long double, sin(x) will call sinl (the long
double version of sin); and if x is a complex number, sin(x) will call the appropriate version of the sin function for that complex type (csin, csinf or csinl).
Inline Functions
[Note: This section can be taught after Section 5.5.]
C99 allows the declaration of inline functions (as C++ does) by placing the keyword inline before the function declaration, as in:
inline void randomFunction();

This has no effect on the logic of the program from the users perspective, but it can improve performance. Function calls take time. When we declare a function as inline, the
program no longer calls that function. Instead, the compiler replaces every call to an inline
function with the code body of that function. This improves the runtime performance but
it may increase the programs size. Declare functions as inline only if they are short and
called frequently. The inline declaration is only advice to the compiler, which can decide
to ignore it. [For more information, see C99 Standard Section 6.7.4.]

Return Without Expression


[Note: This section can be taught after Section 5.5.]
C99 adds tighter restrictions on returning from functions. In functions that return a nonvoid value, we are no longer permitted to use the statement
return;

In C89 this is allowed but results in undefined behavior if the caller tries to use the returned value of the function. Similarly, in functions that do not return a value, we are no
longer permitted to return a value. Statements such as:
void returnInt() { return 1; }

are no longer allowed. C99 requires that compatible compilers produce warning messages
or compilation errors in each of the preceding cases. [For more information, see C99 Standard Section 6.8.6.4.]

Predefined Identifier
[Note: This section can be taught after Section 13.5.]
The __func__ predefined identifier is similar to the __FILE__ and __LINE__ preprocessor
macrosit is a string that holds the name of the current function. Unlike __FILE__, it is
not a string literal but a real variable, so it cannot be concatenated with other literals. This
is because string literal concatenation is performed during preprocessing, and the preprocessor has no knowledge of the semantics of the C language proper.

__func__

2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

G.15 Web Resources

XCIX

Macro
[Note: This section can be taught after Section 14.3.]
Section 14.3 introduced the <stdarg.h> header and facilities for working with variablelength argument lists. C99 adds the va_copy macro, which takes two va_lists and copies
its second argument into its first argument. This allows for multiple passes over a variablelength argument list without starting from the beginning each time.
va_copy

G.15 Web Resources


www.open-std.org/jtc1/sc22/wg14/

Official site for the C standards committee. Includes defect reports, working papers, projects and
milestones, the rationale for the C99 standard, contacts and more.
www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

A draft of the C Standard with Technical Corrigenda 1, 2 and 3, last updated September 7, 2007.
(Available free of charge).
www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf

White paper: Rationale for International StandardProgramming LanguagesC. This 224-page


document describes the C99 standards committee deliberations.
webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2fISO%2fIEC+9899-1999+(R2005)

Purchase an electronic version of the C99 Standard.

www.wiley.com/WileyCDA/WileyTitle/productCd-0470845732.html

Purchase a hard copy of the C99 standard.


gcc.gnu.org/c99status.html

Find the status of C99 features in the GNU Compiler Collection (GCC).
blogs.msdn.com/vcblog/archive/2007/11/05/iso-c-standard-update.aspx

Blog post of Arjun Bijanki, the test lead for the Visual C++ compiler. Discusses the upcoming C1x
standard and why C99 is not supported in Visual Studio.
docs.sun.com/source/817-5064/c99.app.html#98079

Lists the features of C99 supported by the Solaris operating environment.


www.digitalmars.com

Download C/C++ compiler for Win32, a free compiler of most of C99.


www.cs.virginia.edu/~lcc-win32/

Download lcc-win32, a free compiler of most of C99.


www.openwatcom.org

Download Watcom C/C++ compiler, a free compiler of most of C99 by SciTech Software Inc. and
Sybase.
developers.sun.com/sunstudio/index.jsp

Download Sun Studio, which includes a free fully compliant C99 compiler.
www-128.ibm.com/developerworks/linux/library/l-c99.html?ca=dgr-lnxw961UsingC99

Article: Open Source Development Using C99, by Peter Seebach. Discusses C99 library features
on Linux and BSD.
www.informit.com/guides/content.aspx?g=cplusplus&seqNum=215

Article: A Tour of C99, by Danny Kalev. Summarizes some of the new features in the C99 standard.
home.datacomm.ch/t_wolf/tw/c/c9x_changes.html

Provides brief technical descriptions and code examples for many C99 features.
david.tribble.com/text/cdiffs.htm

Article: Incompatibilities Between ISO C89 and ISO C++, by David Tribble. Lists and explains
the areas in which ANSI C, C99, and C++ 98 differ.
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

Appendix G Introduction to C99

Summary
Section G.1 Introduction

C99 is a revised standard for the C programming language that refines and expands the capabilities of C89. C99 has not been widely adopted, and not all popular C compilers support it.

Section G.2 Support for C99

Most C and C++ compilers did not support C99 when it was released.

Section G.4 // Comments

C99 allows you to use // comments (as C++, Java, and C# do).
Whenever the characters // appear outside quotation marks, the rest of the line is treated as a
comment.

Section G.5 Mixing Declarations and Executable Code

C99 allows mixing declarations and executable code.


A variable can be declared anywhere within a block before the variables use.

Section G.6 Declaring a Variable in a for Statement Header

C99 expands on the C89 definition of the for statement, allowing the initialization clause to include a declaration.
Rather than having to use an existing variable as a loop counter, we can create a new loop-counter
variable in the for statement header whose scope is limited to the for statement.

Section G.7 Designated Initializers and Compound Literals

Designated initializers allow you to initialize the elements of an array, union or struct explicitly
by subscript or name.

Section G.8 Type bool

The C99 boolean type is _Bool, which can hold only the values 0 or 1.
C99 provides the <stdbool.h> header file, which defines macros representing the type bool and
its values (true and false). These macros replace true with 1, false with 0 and bool with the
C99 keyword _Bool.

Section G.9 Implicit int Function Declarations

In C89, if a function does not have an explicit return type, it implicitly returns an int.
C99 disallows the use of the implicit int, requiring that C99-compliant compilers issue either a
warning or an error.

Section G.10 Complex Numbers

The C99 standard introduces support for complex numbers and complex arithmetic.
For C99 to recognize complex, we must include the <complex.h> header. This will expand the
macro complex to the keyword _Complex.

Section G.11 Variable-Length Arrays

A variable-length array is an array whose length, or size, is defined in terms of an expression evaluated at execution time.
In C89 sizeof is always a compile-time operation, but when applied to a VLA in C99, sizeof
operates at runtime.
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

Summary

CI

As with fixed-length arrays, there is no protection against stepping outside the array bounds of
VLAs.
The syntax for passing VLAs as parameters to functions is the same as with a normal, fixed-length
array.
All but the first subscript of a multi-dimensional array must be specified when declaring a function parameter. The same restriction holds true for C99, except the sizes can be specified by variables. The initial value of col passed to the function is used to convert from two-dimensional
indices to offsets into the contiguous memory the array is stored in, just as with a fixed-size array.
Changing the value of col inside the function will not cause any changes to the indexing, but
passing an incorrect value to the function will.

Section G.12 The snprintf Function: Helping Avoid Hacker Attacks

The snprintf function helps prevent buffer overflows, a popular form of hacker attack.
The snprintf function returns the number of characters that would have been stored in the destination array if it was large enough, not counting the terminating null character.
If the return value and length of the formatted string are equal, it means that there was no truncation due to the buffer being too small.

Section G.13 Additions to the Preprocessor

The _Pragma operator functions like the #pragma directive_Pragma ( "tokens" ) has the same
effect as #pragma tokens, but is more flexible because it can be used inside a macro definition.
C99 specifies three standard pragmas that deal with the behavior of floating-point operations.
The first token in these standard pragmas is always STDC, the second is one of FENV_ACCESS,
FP_CONTRACT or CX_LIMITED_RANGE, and the third is ON, OFF or DEFAULT to indicate whether the
given pragma should be enabled, disabled, or set to its default value, respectively.
The C99 preprocessor allows passing empty arguments to a macro call. When an empty macro
argument is used with the # or ## operator, the result is the empty string or the identifier the
argument was concatenated with, respectively.
C99 adds variable-length argument lists for macros. This allows for macro wrappers around
functions like printf.
The identifier __VA_ARGS__ is a placeholder for the variable-length argument list.

Section G.14 Other C99 Features

C99 gives minimum limits on compiler resource requirements, such as length of identifiers and
number of elements of a struct or union.
The keyword restrict is used to declare restricted pointers. We declare a restricted pointer when
a pointer should have exclusive access to a region of memory. This enables the compiler to perform certain optimizations.
C99 always performs integer division (and integer modulus) by rounding the quotient toward
zero. This makes integer division reliableC99-compliant platforms all treat integer division in
the same way.
C99 allows us to declare an array of unspecified length as the last member of a struct. A flexible
array member is declared by specifying empty square brackets ([]).
In C99, it is no longer required that aggregates such as arrays, structs, and unions be initialized
by constant expressions.
The type long long int increases the range of values over those of other integer types. It works
only with compatible 64-bit hardware and software.

2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

CII

Appendix G Introduction to C99

The <tgmath.h> header provides type-generic macros for many math functions in <math.h>. For
example, the expression sin(x) will call sinf, sin or sinl if x is a float, double or long double,
respectively. Complex equivalents of the <math.h> functions are also supported.
C99 allows us to declare inline functions (as C++ does) by placing the keyword inline before
the function declaration. The compiler replaces every call to an inline function with the code
body of that function.
In C99 functions that return a value, we are no longer permitted to use the void statement return.
In C99 functions that do not return a value, we are no longer permitted to return a value.
The __func__ predefined identifier is similar to the __FILE__ and __LINE__ preprocessor macrosit is a string that holds the name of the current function.
The va_copy macro takes two va_lists and copies its second argument into its first argument.
This allows for multiple passes over a variable-length argument list without starting from the beginning each time.

Terminology
single-line comment LXXX
LXXXVII
boolean type LXXXVII
C99 LXXIX
compound literal LXXXV
designated initializer LXXXIV
flexible array member XCVII
__func__ predefined identifier XCVIII
//

_Bool

mixing declarations and executable


code LXXXI
_Pragma operator XCV
restricted pointer XCVI
<stdbool.h> LXXXVII
__VA_ARGS__ identifier XCV
va_copy macro XCIX
variable-length array (VLA) XC

Self-Review Exercises
G.1

Fill in the blanks in each of the following statements:


allow us to initialize elements of an array explicitly by subscript.
a)
header and use the type
.
b) For boolean variables, we include the
c) An array whose length is defined in terms of a value determined at execution time is a(n)
.
and
.
d) The only two values a _Bool can hold are

G.2

State whether each of the following is true or false. If false, explain why.
a) C99 allows us to declare variables after their use in the program.
b) If you include the <complex.h> header, you can use the complex type.
c) All code that is valid in C89 is valid in C99.
d) A variable-length array can change in size during its lifetime.
e) If we declare a variable in a for statement, we cannot access that same variable outside
the for statement.
f) // indicates where a comment begins and another // indicates where the comment
ends.

Answers to Self-Review Exercises


G.1

a) Designated initializers. b) <stdbool.h>, bool. c) variable-length array. d) 1, 0.

G.2

a) False. Variables must be declared before their use in the program.


b) True.
2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

Exercises

CIII

c) False. Some practices, such as the implicit int practice, are allowed in C89 but not allowed in C99.
d) False. A variable-length array has a constant size once it is declared (at execution time).
e) True.
f) False. Another // on the same line is treated as part of the first comment and another
// on a different line acts as the start of a separate comment.

Exercises
G.3
(Complex Numbers) Using complex numbers, write a program that solves a quadratic equation of the form ax2 + bx + c = 0 for x by prompting the user for the real values of a, b, and c and
printing the two roots to the screen. Recall that a solution for a quadratic equation can be solved
using the following calculations (shown below as C code):
X1 = ( -b + csqrt( cpow( b, 2.0 ) - 4.0 * a * c ) ) / ( 2.0 * a );
X2 = ( -b - csqrt( cpow( b, 2.0 ) - 4.0 * a * c ) ) / ( 2.0 * a );

G.4
(Variable Declarations in a for Statement Header) Use C99 variable declarations in for
statement headers to solve the following problem. Read in 20 numbers, each between 10 and 100,
inclusive. As each number is read, print it only if it is not a duplicate of a number already read. Provide for the worst case in which all 20 numbers are different. Use the smallest possible array to solve
this problem.
G.5
(Using _Bool) Write a function multiple that determines for a pair of integers whether the
second integer is a multiple of the first. The function should take two integer arguments and return
true if the second is a multiple of the first, and false otherwise. Use this function in a program that
inputs a series of pairs of integers
G.6
(Variable-Length Array) Write a program that sums a sequence of integers. Assume that the
first integer read with scanf specifies the number of values remaining to be entered. Use a variablelength array to store the input values. Your program should read only one value each time scanf is
executed. A typical input sequence might be
5 100 200 300 400 500

2010 Pearson Education, Inc., Upper Saddle River, NJ. All Rights Reserved.

Das könnte Ihnen auch gefallen