A Little C Primer

Download as pdf or txt
Download as pdf or txt
You are on page 1of 36

A Little C Primer

Contents
0.1

Wikibooks:Collections Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

0.1.1

What is Wikibooks? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

0.1.2

What is this book? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

0.1.3

Who are the authors?

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

0.1.4

Wikibooks in Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

0.1.5

Happy Reading!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Introduction to C; Functions; Control Constructs

1.1

An Introductory C Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.2

C Functions in Detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.3

C Control Constructs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

C Variables, Operators & Preprocessor Directives

2.1

C Variables, Declarations and Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2.2

C Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

2.3

C Preprocessor Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13

C Input & Output

15

3.1

C Console IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15

3.2

C File-IO Through Library Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

3.3

C File-IO Through System Calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

19

C Library Functions & Other Comments

21

4.1

C Math Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

21

4.2

C Standard Utility Library & Time Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

21

4.2.1

further reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

The C sprintf Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

4.3.1

C STRING FUNCTION LIBRARY . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

4.4

C String Function Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

4.5

C Character Class Test Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

24

4.6

C Command Line Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

24

4.7

Pointers to C Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

25

4.8

C Dynamic Memory Allocation & Deallocation . . . . . . . . . . . . . . . . . . . . . . . . . . .

25

4.9

Common Programming Problems in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

26

4.3

ii
5

CONTENTS
C Quick Reference

28

5.1

28

Comments and Revision History

30

6.1

30

Comments and Revision History . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Resources and Licensing

31

7.1

Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

31

7.1.1

Wikimedia Resources

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

31

7.1.2

Other Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

31

Licensing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

31

7.2.1

31

7.2

C Quick Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Licensing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Text and image sources, contributors, and licenses

32

8.1

Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

8.2

Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

33

8.3

Content license . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

33

0.1. WIKIBOOKS:COLLECTIONS PREFACE

0.1 Wikibooks:Collections Preface 0.1.2 What is this book?


This book was created by volunteers at Wikibooks (http:
//en.wikibooks.org).

0.1.1

What is Wikibooks?

This book was generated by the volunteers at Wikibooks,


a team of people from around the world with varying
backgrounds. The people who wrote this book may not
be experts in the eld. Some may not even have a passing
familiarity with it. The result of this is that some information in this book may be incorrect, out of place, or
misleading. For this reason, you should never rely on a
community-edited Wikibook when dealing in matters of
medical, legal, nancial, or other importance. Please see
our disclaimer for more details on this.
Despite the warning of the last paragraph, however, books
at Wikibooks are continuously edited and improved. If
errors are found they can be corrected immediately. If
you nd a problem in one of our books, we ask that you
be bold in xing it. You don't need anybodys permission
to help or to make our books better.

Wikibooks runs o the assumption that many eyes can


nd many errors, and many able hands can x them. Over
time, with enough community involvement, the books at
Wikibooks will become very high-quality indeed. You
are invited to participate at Wikibooks to help make
our books better. As you nd problems in your book
don't just complain about them: Log on and x them!
This is a kind of proactive and interactive reading experience that you probably aren't familiar with yet, so log
Started in 2003 as an oshoot of the popular Wikipedia on to http://en.wikibooks.org and take a look around at
project, Wikibooks is a free, collaborative wiki website all the possibilities. We promise that we won't bite!
dedicated to creating high-quality textbooks and other educational books for students around the world. In addition to English, Wikibooks is available in over 130 lan- 0.1.3 Who are the authors?
guages, a complete listing of which can be found at http:
//www.wikibooks.org. Wikibooks is a wiki, which The volunteers at Wikibooks come from around the
means anybody can edit the content there at any time. world and have a wide range of educational and profesIf you nd an error or omission in this book, you can sional backgrounds. They come to Wikibooks for diflog on to Wikibooks to make corrections and additions ferent reasons, and perform dierent tasks. Some Wikas necessary. All of your changes go live on the website ibookians are prolic authors, some are perceptive ediimmediately, so your eort can be enjoyed and utilized tors, some fancy illustrators, others diligent organizers.
by other readers and editors without delay.
Some Wikibookians nd and remove spam, vandalism,
Books at Wikibooks are written by volunteers, and can
be accessed and printed for free from the website. Wikibooks is operated entirely by donations, and a certain portion of proceeds from sales is returned to the Wikimedia
Foundation to help keep Wikibooks running smoothly.
Because of the low overhead, we are able to produce and
sell books for much cheaper then proprietary textbook
publishers can. This book can be edited by anybody at
any time, including you. We don't make you wait two
years to get a new edition, and we don't stop selling old
versions when a new one comes out.
Note that Wikibooks is not a publisher of books, and
is not responsible for the contributions of its volunteer
editors. PediaPress.com is a print-on-demand publisher
that is also not responsible for the content that it prints.
Please see our disclaimer for more information: http://
en.wikibooks.org/wiki/Wikibooks:General_disclaimer .

and other nonsense as it appears. Most Wikibookians


perform a combination of these jobs.
Its dicult to say who are the authors for any particular book, because so many hands have touched it and so
many changes have been made over time. Its not unheard
of for a book to have been edited thousands of times by
hundreds of authors and editors. You could be one of them
too, if you're interested in helping out.

0.1.4 Wikibooks in Class


Books at Wikibooks are free, and with the proper editing and preparation they can be used as cost-eective
textbooks in the classroom or for independent learners.
In addition to using a Wikibook as a traditional readonly learning aide, it can also become an interactive class

CONTENTS

project. Several classes have come to Wikibooks to write


new books and improve old books as part of their normal course work. In some cases, the books written by
students one year are used to teach students in the same
class next year. Books written can also be used in classes
around the world by students who might not be able to
aord traditional textbooks.

0.1.5

Happy Reading!

We at Wikibooks have put a lot of eort into these books,


and we hope that you enjoy reading and learning from
them. We want you to keep in mind that what you are
holding is not a nished product but instead a work in
progress. These books are never nished in the traditional sense, but they are ever-changing and evolving to
meet the needs of readers and learners everywhere. Despite this constant change, we feel our books can be reliable and high-quality learning tools at a great price, and
we hope you agree. Never hesitate to stop in at Wikibooks and make some edits of your own. We hope to see
you there one day. Happy reading!

Chapter 1

Introduction to C; Functions; Control


Constructs
1.1 An Introductory C Program

C compilation is a multi-pass process. To create a program, a C compiler system performs the following steps:
It runs the source le text through a C preprocessor. All this does is perform various text manipulations on the source le, such as macro expansion,
constant expansion, le inclusion, and conditional compilation, which are also explained later.
The output of the preprocessor is a second-level
source le for actual compilation. You can think of
the C preprocessor as a sort of specialized automatic
text editor.

Heres a simple C program to calculate the volume of a


sphere:
/* sphere.c */ #include <stdio.h> /* Include header le
for printf. */ #dene PI 3.141592654f /* Dene a constant. */ static oat sphere(oat); /* Function prototype.
sphere is given internal linkage with the keyword 'static'
since it isn't used outside of this translation unit. */
int main(void) /* Main function. */ { oat volume; /*
Dene a oat variable. */ oat radius = 3; /* Dene
and initialize variable. */ volume = sphere(radius); /*
Call sphere and copy the return value into volume. */
printf( Volume: %f\n, volume ); /* Print the result.
*/ return 0; } oat sphere(oat rad) /* Denition of a
volume calculating function. */ { oat result; /* result
is dened with an automatic storage duration and block
scope. */ result = rad * rad * rad; result = 4 * PI * result
/ 3; return result; /* result is returned to the function
which called sphere. */ }

Next, it runs the second-level source le through the


compiler proper, which actually converts the source
code statements into their binary equivalents. That
is, it creates an object le from the source le.
The object le still cannot be executed, however. If
it uses C library functions, such as printf()" in the
example above, the binary code for the library functions has to be merged, or linked, with the program object le. Furthermore, some addressing information needs to be linked to the object le so it
can actually be loaded and run on the target system.

The rst feature that can be observed in this program is


that comments are enclosed by "/*" and "*/". Comments
can go almost anywhere, since the compiler ignores them.
Another obvious feature is that individual statements in
the program end with a ";". Either forgetting a ";" or
adding one where it isn't needed is a common C programming bug. Lines of code are grouped into blocks by using
curly brackets ("{ }").

These linking tasks are performed by a linker, which


takes one or more object les and links them to binary
library les to create an executable le that can actually
be run.

C is case-sensitive. All C keywords are in lower-case.


Program variable and function names in whatever case
desired, but by convention they should be in lower case.
Constants, to be discussed a bit later, are upper case by
convention.

Commands intended for the C preprocessor, instead of


the C compiler itself, start with a "#" and are known as
preprocessor directives or metacommands. The example program above has two such metacommands:

C has a large number of libraries and library functions. C


by itself has few statements, so much of its functionality
is implemented as library calls.

#include <stdio.h> #dene PI 3.14

Not all the lines in a C program are executable statements.


Some of the statements shown above are preprocessor The rst statement, "#include <stdio.h>;", simply merges
directives.
the contents of the le stdio.h into the current program
3

CHAPTER 1. INTRODUCTION TO C; FUNCTIONS; CONTROL CONSTRUCTS

le before compilation. The stdio.h le contains decla- The declarations of volume, radius, and result specrations required for use of the standard-I/O library, which ify a oating-point variable. The declaration allows variprovides the printf()" function.
ables to be initialized when declared if need be, in this
Incidentally, the stdio.h le, or header le, only con- case declaring radius and assigning it a value of 3.
tains declarations. The actual code for the library is contained in separate library les that are added at link time.
Custom header les loaded with custom declarations can
be created if needed, and then included in a program as
follows:

All three of these declarations dene variables block


scope. Variables with block scope exist only within the
blocks that declare them. Variables of the same name
could be declared in dierent blocks without interference. It is also possible to declare variables with le scope
that can be shared by all functions by declaring them out#include mydefs.h
side of all blocks within a translation unit. By default, all
identiers with le scope are given external linkage. It is
Angle brackets ("< >") are not used with custom header only with the keyword static that an identier is given
les. They only are used to dene the default header internal linkage. Declarations like this:
les provided standard with a C compiler (and which, on
Unix/Linux systems, are found in directory "/usr/include extern int a;
).
A C program is built up of one or more functions. identify a as an int whose storage is dened elsewhere;
preferably in another translation unit.
The program above contains two user-dened functions,
main()" and sphere()", as well as the printf()" library /* global.c */ #include <stdio.h> void somefunc( void
); int globalvar; void main() { extern int globalvar;
function.
The main()" function is mandatory when writing a self- globalvar = 42; somefunc(); printf( "%d\n, globalvar );
contained program. It denes the function that is auto- } void somefunc( void ) { extern int globalvar; printf(
matically executed when the program is run. All other "%d\n, globalvar ); globalvar = 13; }
functions will be directly or indirectly called by main()".
A C function is called simply by specifying its name, with
any arguments enclosed in following parentheses, with
commas separating the arguments. In the program above,
the printf()" function is called as follows:
printf( Volume: %f\n, volume );

Besides the variable declarations, the example programs


above also feature a function declaration, or function
prototype, that allows the C compiler to perform checks
on calls to the function in the program and ag an error
if they are not correct:
oat sphere(oat);

This invocation provides two arguments. The rst -Volume: %f\n -- supplies text and some formatting in- The function prototypes declare the type of value the
formation. The second -- volume -- supplies a numeric function returns (the type will be void if it does not return a value), and the arguments that are to be provided
value.
with the function.
A function may or may not return a value. The sphere()"
Finally, the printf()" library function provides text outfunction does, and so is invoked as follows:
put capabilities for the program. The printf()" function
volume = sphere( radius );
can be used to print a simple message as follows:
printf( Hello, world!" );
A function uses the return keyword to return a value. In
the case of sphere, it returns the volume of the sphere
-- displays the text:
with the statement:
Hello, world!
return result;
Remember that printf()" doesn't automatically add a
All variables in a C program must be declared by spec- newline to allow following printf()"s to print on the
ifying their name and type. The example program de- next display line. For example:
clares two variables for the main routine:
printf( Twas bryllig " ); printf( and the slithy toves );
oat volume; oat radius = 3;
-- prints the text:
-- and one in the sphere routine:

Twas bryllig and the slithy toves

oat result;

A newline character ("\n) must be added to force a newline. For example:

1.2. C FUNCTIONS IN DETAIL


printf( Hello,\nworld!" );
-- gives:
Hello, world!

5
/* fdomain.c */ #include <stdio.h>; void func1( void );
void func2( void ); int main() { puts( MAIN ); func1();
func2(); } void func1( void ) { puts( FUNC1 ); func2();
} void func2( void ) { puts( FUNC2 ); func1(); }

These examples only print a predened text constant. It is In this example, main()" can call func1()" and
possible to include format codes in the string and then func2()"; func1()" can call func2()"; and func2()" can
follow the string with one or more variables to print the call func1()". In principle, even
values they contain:
main()" could be called by other functions, but its hard
printf( " Result = %f\n, result );
to gure out why anyone would want to do so. Although
main()" is the rst function in the listing above, theres
no particular requirement that it be so, but by convention
This would print something like:
it always should be.
Result = 0.5
Functions can call themselves recursively. For example,
The "%f is the format code that tells printf to print a func1()" can call func1()" indenitely, or at least until
oating-point number. For another example:
a stack overow occurs. You cannot declare functions
inside other functions.
printf( "%d times %d = %d\n, a, b, a * b );
Functions are dened as follows:
-- would print something like:

oat sphere( int rad ) { ... }

4 times 10 = 40
The "%d prints an integer quantity. Math or string ex- They begin with a function header that starts with a return
pressions and functions can be included in the argument value type declaration (oat in this case), then the function name (sphere), and nally the arguments required
list.
(int rad).
To simply print a string of text, there is a simpler function,
puts()", that displays the specied text and automatically ANSI C dictates that function prototypes be provided to
allow the compiler to perform better checking on function
appends a newline:
calls:
puts( Hello, world!" );
oat sphere( int rad );
Just for fun, lets take a look at what our example program
For an example, consider a simple program that res a
would be like in the pre-ANSI versions of C:
weapon (simply by printing BANG!"):
/* oldspher.c */ #include <stdio.h> #dene PI
3.141592654 oat sphere(); /* Parameters not de- /* bango.c */ #include <stdio.h> void re( void ); void
ned in function prototype. */ main() { oat volume; int main() { printf( Firing!\n ); re(); printf( Fired!\n );
radius = 3; volume = sphere( radius ); printf( Volume: } void re( void ) { printf( BANG!\n ); }
%f\n, volume ); } oat sphere( rad ) int rad; /* Parameter type not specied in function header. */ { oat result; This prints:
result = rad * rad * rad; result = 4 * PI * result / 3; return
Firing! BANG! Fired!
result; }
Since re()" does not return a value and does not acThe following sections elaborate on the principles out- cept any arguments, both the return value and the argument are declared as void"; re()" also does not use a
lined in this section.
return statement and simply returns automatically when
completed.

1.2 C Functions in Detail

Lets modify this example to allow re()" to accept an


argument that denes a number of shots. This gives the
program:

/* re.c */ #include <stdio.h> void re( int n ); void


main() { printf( Firing!\n ); re( 5 ); printf( Fired!\n
As noted previously, any C program must have a main()" ); } void re( int n ) { int i; for ( i = 1; i <= n ; ++i ) {
function to contain the code executed by default when the printf( BANG!\n ); } }
program is run.
A program can contain as many functions as needed. All This prints:
functions are visible to all other functions. For example:

CHAPTER 1. INTRODUCTION TO C; FUNCTIONS; CONTROL CONSTRUCTS

Firing! BANG! BANG! BANG! BANG! BANG! Fired! /* fnarray.c */ #include <stdio.h> #dene SIZE 10 void
This program passes a single parameter, an integer, to the testfunc( int a[] ); void main() { int ctr, a[SIZE]; for( ctr
re()" function. The function uses a for loop to exe- = 0; ctr < SIZE; ++ctr ) { a[ctr] = ctr * ctr; } testfunc( a
cute a BANG!" the specied number of times -- more ); } void testfunc( int a[] ) { int n; for( n = 0; n < SIZE;
++ n ) { printf( "%d\n, a[n] ); } }
on for later.
If a function requires multiple arguments, they can be
It is possible to dene functions with a variable number
separated by commas:
of parameters. In fact, printf()" is such a function. This
printf( "%d times %d = %d\n, a, b, a * b );
is a somewhat advanced issue and we won't worry about
it further in this document.
The word parameter is sometimes used in place of ar- The normal way to get a value out of a function is simply
gument. There is actually a ne distinction between to provide it as a return value. This neatly encapsulates
these two terms: the calling routine species arguments the function and isolates it from the calling routine. In
to the called function, while the called function receives the example in the rst section, the function sphere()"
the parameters from the calling routine.
returned a oat value with the statement:
When a parameter is listed in the function header, it be- return( result );
comes a local variable to that function. It is initialized to
the value provided as an argument by the calling routine.
If a variable is used as an argument, there is no need for The calling routine accepted the return value as follows:
it to have the same name as the parameter specied in the volume = sphere( radius );
function header.
For example:
re( shots ); ... void re( int n ) ...

The return value can be used directly as a parameter to


other functions:
printf( Volume: %f\n, sphere( radius ) );

The integer variable passed to re()" has the name


shots, but re()" accepts the value of shots in a local variable named n. The argument and the parameter
could also have the same name, but even then they would
remain distinct variables.

The return value does not have to be used; printf()", for


example, returns the number of characters it prints, but
few programs bother to check.

A function can contain more than one return statement::


Parameters are, of course, matched with arguments in the if( error == 0 ) { return( 0 ); } else { return( 1 ); }
order in which they are sent:
/* pmmatch.c */ #include <stdio.h> void showme( int a,
int b ); void main() { int x = 1, y = 100; showme( x, y );
} void showme( int a, int b ) { printf( a=%d b=%d\n,
a, b ); }

A return can be placed anywhere in a function. It


doesn't have to return a value; without a value, return
simply causes an exit from the function. However, this
does imply that the data type of the function must be declared as void":

This prints:

void ftest( int somevar ) { ... if( error == 0 ) { return(); }


... }

a=1 b=100

This program can be modied to show that the arguments


are not aected by any operations the function performs If theres no return in a function, the function returns
after it executes its last statement. Again, this means the
on the parameters, as follows:
/* noside.c */ #include <stdio.h> void showmore( int a, function type must be declared void.
int b ); void main() { int x = 1, y = 100; showmore( x, y
); printf( x=%d y=%d\n, x, y ); } void showmore( int
a, int b ) { printf( a=%d b=%d\n, a, b ); a = 42; b =
666; printf( a=%d b=%d\n, a, b ); }

The return statement can only return a single value, but


this value can be a pointer to an array or a data structure.
Pointers are a complicated subject and will be discussed
in detail later.

This prints:
a=1 b=100 a=42 b=666 x=1 y=100
Arrays can be sent to functions as if they were any other
type of variable:

1.3 C Control Constructs

1.3. C CONTROL CONSTRUCTS

C contains a number of looping constructs, such as the known weapon!\n); } }


while loop:
This example can be more easily implemented using an
/* while.c */ #include <stdio.h> void main() { int test = else clause:
10; while( test > 0 ) { printf( test = %d\n, test ); test = /* ifelse.c */ void re( int weapon ) { if( weapon == MIStest - 2; } }
SILE ) { printf( Fired missile!\n ); } else { printf( UnIf test starts with an initial value less than or equal to known weapon!\n); } }
0 the while loop will not execute even once. There is a Since there is only one statement in each clause the curly
variant, do, that will always execute at least once:
brackets aren't really necessary. This example would
/* do.c */ #include <stdio.h> void main() { int test = 10; work just as well:
do { printf( test = %d\n, test ); test = test - 2; } while( void re( int weapon ) { if( weapon == MISSILE ) printf(
test > 0 ); }
Fired missile!\n ); else printf( Unknown weapon!\n );
The most common looping construct is the for loop, }
which creates a loop much like the while loop but in a However, the brackets make the structure more obvious
more compact form:
and prevent errors if you add statements to the conditional
/* for.c */ #include <stdio.h> void main() { int test; for( clauses. The compiler doesn't care one way or another, it
test = 10; test > 0; test = test - 2 ) { printf( test = %d\n, generates the same code.
test ); } }
There is no elseif keyword, but if statements can be
Notice that with all these loops, the initial loop statement nested:
does not end with a ";". If a ";" was placed at the end /* nestif.c */ #include <stdio.h> #dene MISSILE 1 #deof the for statement above, the for statement would ne LASER 2 void re( int weapon ) void main() { re(
execute to completion, but not run any of the statements
LASER ); } void re( int weapon ) { if( weapon == MISin the body of the loop.
SILE ) { printf( Fired missile!\n ); } else { if( weapon
The for loop has the syntax:

== LASER ) { printf( Fired laser!\n ); } else { printf(


for( <initialization>; <operating test>; <modifying ex- Unknown weapon!\n); } } }
pression> )
This is somewhat clumsy. The switch statement does a
All the elements in parentheses are optional. A for loop cleaner job:
could be run indenitely with:
for( ; ; ) { ... }
-- although using an indenite while is cleaner:

/* switch.c */ void re( int weapon ) { switch( weapon )


{ case MISSILE: printf( Fired missile!\n ); break; case
LASER: printf( Fired laser!\n ); break; default: printf(
Unknown weapon!\n); break; } }

while( 1 ) { ... }

The switch statement tests the value of a single variable;


It is possible to use multiple expressions in either the ini- unlike the if statement, it can't test multiple variables.
tialization or the modifying expression with the ", oper- The optional default clause is used to handle conditions
not covered by the other cases.
ator:
/* formax.c */ #include <stdio.h> void main() { int a, b; Each clause ends in a break, which causes execution to
for ( a = 256, b = 1; b < 512 ; a = a / 2, b = b * 2 ) { break out of the switch. Leaving out a break can be
another subtle error in a C program, since if it isn't there,
printf( a = %d b = %d\n, a, b ); } }
execution ows right through to the next clause. However,
The conditional tests available to C are as follows:
this can be used to advantage. Suppose in our example the
a == b equals a != b not equals a < b less than a > b routine can also be asked to re a ROCKET, which is the
greater than a <= b less than or equals a >= b greater than same as a MISSILE:
or equals
void re( int weapon ) { switch( weapon ) { case
The fact that "==" is used to perform the equals test, ROCKET: case MISSILE: printf( Fired missile!\n );
while "=" is used as the assignment operator, often causes break; case LASER: printf( Fired laser!\n ); break; default: printf( Unknown weapon!\n); break; } }
confusion and is a common bug in C programming:
a == b Is a equal to b"? a = b Assign value of b to The break statement is not specic to switch statements. It can be used to break out of other control struca.
tures, though good program design tends to avoid such
C also contains decision-making statements, such as if":
improvisations:
/* if.c */ #include <stdio.h> #dene MISSILE 1 void re(
/* break.c */ #include <stdio.h> void main() { int n; for(
int weapon ); void main() { re( MISSILE ); } void re(
n = 0; n < 10; n = n + 1 ) { if( n == 5 ) { break; /* Punch
int weapon ) { if( weapon == MISSILE ) { printf( Fired
out of loop at value 5. */ } else { printf( "%d\n, n ); } }
missile!\n ); } if( weapon != MISSILE ) { printf( Un-

CHAPTER 1. INTRODUCTION TO C; FUNCTIONS; CONTROL CONSTRUCTS

}
If the for loop were nested inside a while loop, a
break out of the
for loop would still leave you stuck in the while loop.
The break keyword only applies to the control construct
that executes it.
There is also a continue statement that skips to the end
of the loop body and continues with the next iteration of
the loop. For example:
/* continue.c */ #include <stdio.h> void main() { int n;
for( n = 0; n < 10; n = n + 1 ) { if( n == 5 ) { continue; }
else { printf( "%d\n, n ); } } }
Finally, there is a goto statement:
goto punchout; ... punchout:
-- that jumps to an arbitrary tag within a function, but
the use of this statement is generally discouraged and it is
rarely seen in practice.
While these are the lot of Cs true control structures, there
is also a special conditional operator that performs a
simple conditional assignment of the form:
if( a == 5) { b = 10; } else { b = 255; }
-- using a much tidier, if more cryptic, format:
b = ( a == 5 ) ? 10 : 255 ;
the ?: construct is called a ternary operator -- or the
ternary operator -- as it takes 3 arguments.

Chapter 2

C Variables, Operators & Preprocessor


Directives
2.1 C Variables, Declarations and
Constants

string
There are a number of special characters dened in C:
'\a' alarm (beep) character '\p' backspace '\f' formfeed '\n' newline '\r' carriage return '\t' horizontal tab
'\v' vertical tab '\\' backslash '\?' question mark '\''
single quote '\"' double quote '\0NN' character code
in octal '\xNN' character code in hex '\0' null character

C supports a exible set of variable types and structures,


as well as common arithmetic and math functions along
with a few interesting operators that are unique to C. This
chapter explains them in detail, and ends with a short discussion of preprocessor commands.

Symbolic constants can be specied using the dene


C preprocessor declaration:

C includes the following fundamental data types:

These are representative values. The denitions tend to


#dene PI 3.141592654
vary between implementations. For example, in some
systems an int is 16 bits, and a long double could be There is also a const declaration that denes a read-only
64 bits. The only thing that is guaranteed is the prece- variable, such as a memory location in ROM:
dence:
const int a;
short <= int <= long oat <= double <= long double
Arrays can be declared and initialized:
One peculiarity of C that can lead to maddening problems is that while there is an unsigned char data type,
int myarray[10]; unsigned int list[5] = { 10, 15, 12,
for some reason many functions that deal with individual
19, 23 }; oat rdata[128], grid[5][5];
characters require variables to be declared int or unAll C arrays have a starting index of 0, so list has the insigned int.
dexes 0 through 4. Elements in rdata would be accessed
Declarations are of the form:
as follows:
int myval, tmp1, tmp2; unsigned int marker1 = 1,
for( i = 0; i <= 127; i = i + 1 ) { printf ( "\f\n, rdata[i]
marker2 = 10; oat magnitude, phase;
); }
Variable names can be at least 31 characters long, though
C does not perform rigorous bounds checking on array
modern compilers will always support longer names.
access. It is easy to overrun the bounds of the array,
Variables names can be made up of letters, digits, and
and the only symptom will be that the program acts very
the "_ (underscore) character; the rst character must
strangely.
be a letter. While it is possible to use uppercase letters
in variable names, conventional C usage reserves upper Of particular importance are arrays of characters,
case for constant names. A leading "_ is also legal, but
which are used to store
is generally reserved for marking internal library names.
C allows several variables to be declared in the same statement, with commas separating the declarations. The vari- strings:
ables can be initialized when declared. Constant values char s[128]; strcpy( s, This is a test!");
for declarations can be declared in various formats:
The string This is a test!" is used to initialize s through
128 decimal int 256u decimal unsigned int 512l the strcpy()" function, discussed in a later chapter. The
decimal long int 0xAF hex int 0173 octal int 0.243 stored string will contain a terminating null character
oat 0.1732f oat 15.75E2 oat 'a' character giday (the character with ASCII code 0, represented by '\0').
9

10

CHAPTER 2. C VARIABLES, OPERATORS & PREPROCESSOR DIRECTIVES

The null is used by C functions that manipulate strings to a pointer to the string it denes. This means that in the
determine where the end of the string is, and it is impor- following operation:
tant to remember the null is there.
char *p; p = Life, the Universe, & Everything!";
The curious reader may wonder why the strcpy()" func- -- p ends up being a pointer to the memory in which
tion is needed to initialize the string. It might seem to be
the C compiler stored the string literal, and p[0]" would
easier to do:
evaluate to L. In a similar sense, the following operachar s[128] = This is a test!";

tion:

In fact, this is an absurd operation, but to explain why, the


char ch; ch = Life, the Universe, & Everyconcept of pointers must be introduced.
thing!"[0];
-- would put the character L into the variable ch.
C programs can dene pointers that contain the adThis is very well and good, but why care? The reason to
dress of a variable or
care is because this explains why the operation:
an array. For example, a pointer could be dened named:

char s[128] = This is a test!";

-- is absurd. This statement tells the C compiler to reserve 128 bytes of memory and set a pointer named s
-- that gives the address of a variable, rather than the vari- to point to them. Then it reserves another block of memable itself. A value could then be put into that location ory to store This is a test!" and points s to that. This
with the statement:
means the block of 128 bytes of memory that were originally allocated is now sitting empty and unusable, and
*ptr = 345;
the program is actually accessing the memory that stores
In an inverse fashion, the address of a variable can be
This is a test!".
obtained with "&":
This will seem to work for a while, until the program tries
int tmp; somefunc( &tmp );
to store more bytes into that block than can t into the 16
To sum up:
bytes reserved for This is a test!". Since C is poor about
bounds checking, this may cause all kinds of trouble.
A pointer is declared in the form: "*myptr.
This is why strcpy()" is usually necessary. It isn't needed
for a string that won't modied or will not be used to store
If myvar is a variable, then "&myvar is a pointer
more data than it is initialized to, and under such circumto that variable.
stances the following statements will work ne:
If myptr is a pointer, then "*myptr gives the vari- char *p; p = Life, the Universe, & Everything! ";
able data for that pointer.
These issues become particularly tricky when passing
strings as parameters to functions. The following examPointers are useful because they allow a function to re- ple shows how to get around the pitfalls:
turn a value through a parameter variable. Otherwise,
/* strparm.c */ #include <stdio.h> #inthe function will simply get the data the variable contains
clude <string.h> char *strtest( char *a,
and have no access to the variable itself.
char *b ); int main () { char a[256], b[256],
One peculiar aspect of C is that the name of an array ac- c[256];
strcpy( a, STRING A: ABCDEtually species a pointer to the rst element in the array. FGHIJKLMNOPQRSTUVWXYZ0123456789
For example, given the string declaration:
);
strcpy( b, STRING B: ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ); strcpy(
char s[256];
c, STRING C: ABCDEFGHIJKLMNOPQRSTU-- then the function call:
VWXYZ0123456789 ); printf( Initial values of
somefunc( s )
strings:\n ); printf( "\n ); printf( " a = %s\n,
-- will actually pass the address of the character array to a ); printf( " b = %s\n, b ); printf( " c = %s\n,
the function, and the function will be able to modify it. c ); printf( "\n ); strcpy( c, strtest( a, b )); printf(
Final values of strings:\n ); printf( "\n ); printf(
However:
" a = %s\n, a ); printf( " b = %s\n, b ); printf(
s[12]
" c = %s\n, c ); printf( "\n ); return 0; } char
-- gives the value in the array value with index 12. Re- *strtest( char *x, char *y ) { printf( Values passed
member that this is the 13th element, since indexes al- to function:\n ); printf( "\n ); printf( " x = %s\n,
x ); printf( " y = %s\n, y ); printf( "\n ); strcpy(
ways start at 0.
y, NEWSTRING B: abcdefghijklmnopqrstuThere are more peculiarities to strings in C. Another invwxyz0123456789 ); return NEWSTRING C:
teresting point is that a string literal actually evaluates to
int *ptr;

2.1. C VARIABLES, DECLARATIONS AND CONSTANTS


abcdefghijklmnopqrstuvwxyz0123456789"; }
It is possible to dene structures in C, which are
collections of dierent data elements:
/* struct.c */ #include <stdio.h> #include <string.h>
struct person /* Dene structure type. */ { char
name[50]; int age; oat wage; }; void display( struct
person ); int main() { struct person m; /* Declare an
instance of it. */ strcpy( m.name, Coyote, Wile E.
); /* Initialize it. */ m.age = 41; m.wage = 25.50f;
display( m ); return 0; } void display( struct person
p ) { printf( Name: %s\n, p.name ); printf( Age:
%d\n, p.age ); printf( Wage: %4.2f\n, p.wage );
}
This program has a few interesting features:

11
C contains a concept similar to a structure known
as a union. A union is declared in much the same
way as a structure. For example:
union usample { char ch; int x; }
The dierence is that the union can store either of these
values, but not both at the same time. A char value or
an int value can be stored in an instance of the union dened above, but its not possible to store both at the same
time. Only enough memory is allocated for the union to
store the value of the biggest declared item in it, and that
same memory is used to store data for all the declared
items. Unions are not often used and will not be discussed
further.
The following example program shows a practical
use of structures. It tests a set of functions that perform operations on three-dimensional vectors:

The structure has to be dened by a struct declaration before it can declare any structures themselves. vadd(): Add two vectors. vsub(): Subtract two vecIn this case we dene a struct of type person.
tors. vdot(): Vector dot product. vcross(): Vector
cross product. vnorm(): Norm (magnitude) of vec Instances of the struct (m) are then declared as by tor. vangle(): Angle between two vectors. vprint():
dening the structure type (struct person).
Print out vector.
Elements of the structure are accessed with a dot The program follows:
notation (m.name, m.age, and m.wage).
/* vector.c */ #include <stdio.h> #include <math.h>
#dene PI 3.141592654 struct v { double i, j, k; };
A structure can be copied to another structure with a sin- void vadd( struct v, struct v, struct v* ); void vprint(
gle assignment statement, as long as the structures are of struct v ); void vsub( struct v, struct v, struct v* );
double vnorm( struct v ); double vdot( struct v, struct
the same type:
v ); double vangle( struct v, struct v ); void vcross(
struct person m, n; ... m = n;
struct v, struct v, struct v* ); int main() { struct v
v1 = { 1, 2, 3 }, v2 = { 30, 50, 100 }, v3; double a;
It is also possible to declare arrays of structures:
printf( Sample Vector 1: " ); vprint( v1 ); printf(
struct person group[10]; ... strcpy( group[5].name, Sample Vector 2: " ); vprint( v2 ); vadd( v1, v2,
McQuack, Launchpad );
&v3 ); printf( Vector Add: " ); vprint( v3 ); vsub(
-- or even embed structures inside structure declarations: v1, v2, &v3 ); printf( Vector Subtract: " ); vprint(
v3 ); vcross( v1, v2, &v3 ); printf( Cross Product:
struct trip_rec { struct person traveler; char dest[50];
" ); vprint( v3 ); printf( "\n ); printf( Vector 1
int date[3]; int duration; oat cost; }
Norm: %f\n, vnorm( v1 ) ); printf( Vector 2 Norm:
-- in which case the nested structure would be accessed %f\n, vnorm( v2 ) ); printf( Dot Product: %f\n,
as follows:
vdot( v1, v2 ) ); a = 180 * vangle( v1, v2) / PI ; printf(
struct trip_rec t1; ... strcpy( t1.traveler.name, Mar- Angle: %3f degrees.\n, a ); return 0; } void vadd(
struct v a, struct v b, struct v *c ) /* Add vectors. */ {
tian, Marvin );
c->i = a.i + b.i; c->j = a.j + b.j; c->k = a.k + b.k; }
The name of a structure denes a variable, not an ad- double vangle( struct v a, struct v b ) /* Get angle bedress. If the name of a structure is passed to a function, tween vectors. */ { double c; c = vdot( a, b ) / ( vnorm(
the function works only on its local copy of the structure. a ) * vnorm( b ) ); return acos( c ); } void vcross( struct
To return values, an address must be specied:
v a, struct v b, struct v *c ) /* Cross product. */ { c->i
= a.j * b.k - a.k * b.j; c->j = a.k * b.i - a.i * b.k; c->k
setstruct( &mystruct );
= a.i * b.j - a.j * b.i; } double vdot( struct v a, struct
There is a shorthand way to get at the elements of a struc- v b ) /* Dot product of vectors. */ { return a.i * b.i +
ture with the pointer to the structure instead of the struc- a.j * b.j + a.k * b.k; } double vnorm ( struct v a ) /*
ture itself. If sptr is a pointer to a structure of type Norm of vectors. */ { return sqrt( a.i * a.i + a.j * a.j
person, its elds can be accessed as follows:
+ a.k * a.k ); } void vprint ( struct v a ) /* Print vector.
strcpy( sptr->name, Leghorn, Foghorn ); sptr- */ { printf( " I = %6.2f J = %6.2f K = %6.2f\n, a.i,
>age = 50; sptr->wage = 12.98;
a.j, a.k ); } void vsub ( struct v a, struct v b, struct v

12

CHAPTER 2. C VARIABLES, OPERATORS & PREPROCESSOR DIRECTIVES

*c ) /* Subtract vectors. */ { c->i = a.i - b.i; c->j = a.j


- b.j; c->k = a.k - b.k; }

It is possible to dene custom enumerated types in


C. For example:

The concept of local and global variables should be


clear by now. It is

enum day { saturday, sunday, monday, tuesday,


wednesday, thursday, friday };

-- denes enumerated type day to consist of the valalso possible to declare a local variable as static, mean- ues of the days of the week. In practice, the values are
ing it retains its value from one invocation of the function merely text constants associated to a set of consecutive
to the next. For example:
integer values. By default, the set begins at 0 and counts
#include <stdio.h> void testfunc( void ); int main() { up, so here saturday has the value 0, sunday has the
int ctr; for( ctr = 1; ctr <= 8; ++ctr ) { testfunc(); } value 1, and so on. Any set of number assignments can
return 0; } void testfunc( void ) { static int v; printf( be specied if desired:
"%d\n, 2*v ); ++v; }
enum temps { zero = 0, freeze = 32, boil = 220 };
This prints:

Obviously much the same could be done with sets of


"#dene directives, but this is a much cleaner solution.
Once the type is dened, for example, variables of that
-- since the initial value of a integer is 0 by default. It is
type can be declared as follows:
not a good idea to rely on a default value!
enum day today = wednesday;
0 2 4 6 8 10 12 14

There are two other variable declarations that should The variable today will act as an int variable and will
be recognized, though
allow the operations valid for int variables. Once more,
remember that C doesn't do much in the way of bounds
theres little reason to use them: register, which de- checking, and it is not wise to rely on the C compiler to
clares that a variable should be assigned to a CPU register, give warnings.
and volatile, which tells the compiler that the contents
of the variable may change spontaneously.
Finally, a typedef declaration can be used to dene
custom data types:
There is more and less than meets the eye to these declarations. The register declaration is discretionary: the
variable will be loaded into a CPU register if it can, and typedef ch[128] str;
if not it will be loaded into memory as normal. Since a
good optimizing compiler will try to make the best use of Then variables of this type could be declared as follows:
CPU registers anyway, this is not in general all that useful str name;
a thing to do.
The volatile declaration appears ridiculous at rst sight,
something like one of those joke computer commands
like halt and catch re. Actually, its used to describe a
hardware register that can change independently of program operation, such as the register for a realtime clock.

2.2 C Operators

C supports the following arithmetic operators:


C is fairly exible in conversions between data types.
c = a * b multiplication c = a / b division c = a % b mod
In many cases, the
(remainder division) c = a + b addition c = a - b subtraction
type conversion will happen transparently. If a char
is converted to a short data type, or an int is con- It also supports the following useful (if cryptic) increverted to a long data type, for example, the converted ment and decrement operators:
data type can easily accommodate any value in the origi- ++a increment --a decrement
nal data type.
These operators can also be expressed as a++" and a--".
Converting from a bigger to a smaller data type can lead If the only thing thats needed is an increment or decreto odd errors. The same is true for conversions between ment, the distinction between the two forms is irrelevant.
signed and unsigned data types. For this reason, type However, if a variable is being incremented or decreconversions should be handled carefully, and it is usually mented as a component of some expression, then "++a
preferable to do them explicitly, using a cast operation. means increment the variable rst, then get its value,
For example, a cast conversion can be performed from an while a++" means get the value of the variable rst,
int value to a oat value as follows:
then increment it. Failing to remember this distinction
int a; oat b; ... b = (oat)a;
can lead to subtle programming errors.

2.3. C PREPROCESSOR DIRECTIVES

13

Finally, C supports a set of bitwise operations:

() [] -> . ! ~ ++ -- (cast) & sizeof - (minus prex) / % + a = ~a bit complement a = b << c shift b left by number << >> < <= > >= == != & ^ | && || ?: = += -= *= /= %=
of bits stored in c a = b >> c shift b right by number of >>= <<= &= ^= |= ,
bits stored in c a = b & c b AND c a = b ^ c b XOR c a = Of course, parentheses can be used to control precedence.
b | c b OR c
If in doubt about the order of evaluation of an expression,
C allows math operations to be performed in a shortcut add more parentheses. They won't cause any trouble and
might save some pain.
fashion:
operation shortcut _________________________ a = a Advanced math operations are available as library func* b a *= b a = a / b a /= b a = a % b a %= b a = a + b tions. These will be discussed in a later chapter.
a += b a = a - b a -= b a = a << b a <<= b a = a >> b a
>>= b a = a & b a &= b a = a ^ b a ^= b a = a | b a |= b
_________________________

2.3 C Preprocessor Directives

The C relational operations were discussed in the previous


chapter and are repeated here for completeness:
a == b equals a != b not equals a < b less than a > b We've already seen the "#include and "#dene preprogreater than a <= b less than or equals a >= b greater than cessor directives. The C preprocessor supports several
or equals
other directives as well. All such directives start with a
These are actually math operations that yield 1 if true and "#" to allow them to be distinguished from C language
0 if false. The following operation actually makes syntac- commands.
tic sense:
a = b * ( b < 2 ) + 10 * ( b >= 2 );
This would give a the value b if b is less than 2,
and the value 10 otherwise. This is cute, but not recommended. Its cryptic; may make porting to other languages more dicult; and in this case, it can be done
much more eectively with the conditional operator discussed in the previous chapter:
a = ( b < 2 ) ? b : 10;

As explained in the rst chapter, the "#include directive


allows the contents of other les in C source code:
#include <stdio.h>
Notice that the standard header le stdio.h is specied
in angle brackets. This tells the C preprocessor that the
le can be found in the standard directories designated by
the C compiler for header les. To include a le from a
nonstandard directory, use double quotes:

This conditional operator is also known as the triadic #include "\home\mydefs.h


operator.
Include les can be nested. They can call other include
There are similar logical operators:
les.
! logical NOT && logical AND || logical OR
Also as explained in the rst chapter, the "#dene direcRemember that these are logical operations, not bitwise tive can be used to specify symbols to be substituted for
operations -- don't confuse "&&" and "||" with "&" and specic strings of text:
"|". The distinction is that while the bitwise operators
perform the operations on a bit-by-bit basis, the logical #dene PI 3.141592654 ... a = PI * b;
operations simply assess the values of their operands to
be either 0 or 1 (any nonzero operand value evaluates to In this case, the preprocessor does a simple text substitu1 in such comparisons) and return either a 0 or a 1:
tion on PI throughout the source listing. The C compiler
proper not only does not know what PI is, it never even
if(( A == 5 ) && ( B == 10 )) { ... }
sees it.
Finally, there is a sizeof operand that returns the size of
The "#dene directive can be used to create function-like
a particular operand in bytes:
macros that allow parameter substitution. For example:
int tvar; ... printf ( Size = %d\n, sizeof( int ) );
#dene ABS(value) ( (value) >=0 ? (value) : -(value) )
This comes in handy for some mass storage operations.
The sizeof()" function can be given a data type name or
the name of a variable , and the variable can be an array, This macro could then be used in an expression as follows:
in which case sizeof()" gives the size of the entire array. printf( Absolute value of x = %d\n, ABS(x) );
The precedence of these operators in math functions - that is, which ones are evaluated before others -- are Beware that such function-like macros don't behave exdened as follows, reading from the highest precedence actly like true functions. For example, suppose x++" is
to the lowest:
as an argument for the macro above:

14

CHAPTER 2. C VARIABLES, OPERATORS & PREPROCESSOR DIRECTIVES

val = ABS(x++);
This would result in x being incremented twice because
x++" is substituted in the expression twice:
val = ( (x++) >=0 ? (x++) : -(x++) )
Along with the "#dene directive, there is also an "#undef directive that undenes a constant that has been previously dened:
#undef PI
Another feature supported by the C preprocessor is conditional compilation, using the following directives:
#if #else #elif #endif
These directives can test the values of dened constants
to dene which blocks of code are passed on to the C
compiler proper:
#if WIN == 1 #include WIN.H #elif MAC == 1
#include MAC.H #else #include LINUX.H #endif
These directives can be nested if needed. The "#if and
"#elif can also test to see if a constant has been dened
at all, using the dened operator:
#if dened( DEBUG ) printf( Debug mode!\n); #endif
-- or test to see if a constant has not been dened:
#if !dened( DEBUG ) printf( Not debug mode!\n);
#endif
Finally, there is a "#pragma directive, which by denition is a catch-all used to implement machine-unique
commands that are not part of the C language. Pragmas
vary from compiler to compiler, since they are by denition nonstandard.

Chapter 3

C Input & Output


3.1 C Console IO

board and echo it. kbhit() Check to see if a key has been
pressed.
The printf()" function, as explained previously, prints a
string that may include formatted data:

This chapter covers console (keyboard/display) and le


I/O. You've already seen one console-I/O function,
printf()", and there are several others. C has two separate approaches toward le I/O, one based on library
functions that is similar to console I/O, and a second that
uses system calls. These topics are discussed in detail
below.

printf( This is a test!\n );


-- which can include the contents of variables:
printf( Value1: %d Value2: %f\n, intval, oatval );
The available format codes are:
%d decimal integer %ld long decimal integer %c character %s string %e oating-point number in exponential notation %f oating-point number in decimal notation %g
use %e and %f, whichever is shorter %u unsigned decimal integer %o unsigned octal integer %x unsigned hex
integer

Console I/O in general means communications with the


computers keyboard and display. However, in most
modern operating systems the keyboard and display are
simply the default input and output devices, and user can
easily redirect input from, say, a le or other program and
Using the wrong format code for a particular data type can
redirect output to, say, a serial I/O port:
lead to bizarre output. Further control can be obtained
type inle > myprog > com
with modier codes; for example, a numeric prex can
The program itself, myprog, doesn't know the dier- be included to specify the minimum eld width:
ence. The program uses console I/O to simply read its %10d
standard input (stdin)" -- which might be the keyboard,
a le dump, or the output of some other program -- and This species a minimum eld width of ten characters.
print to its standard output (stdout)" -- which might be If the eld width is too small, a wider eld will be used.
the display or printer or another program or a le. The Adding a minus sign:
program itself neither knows nor cares.
%10d
Console I/O requires the declaration:
#include <stdio.h>

-- causes the text to be left-justied. A numeric precision


can also be specied:

Useful functions include:

%6.3f

printf() Print a formatted string to stdout. scanf() Read


formatted data from stdin. putchar() Print a single character to stdout. getchar() Read a single character from
stdin. puts() Print a string to stdout. gets() Read a line
from stdin.

This species three digits of precision in a eld six characters wide. A string precision can be specied as well,
to indicate the maximum number of characters to be
printed. For example:

/* prtint.c */ #include <stdio.h> int main(void) { printf(


Windows-based compilers also have an alternative library "<%d>\n, 336 ); printf( "<%2d>\n, 336 ); printf(
of console I/O functions. These functions require the dec- "<%10d>\n, 336 ); printf( "<%10d>\n, 336 ); return
0; }
laration:
This prints:
#include <conio.h>
The three most useful Windows console I/O functions are: <336> <336> < 336> <336 >
getch() Get a character from the keyboard (no need to Similarly:
press Enter). getche() Get a character from the key15

16
/* proat.c */ #include <stdio.h> int main(void) { printf(
"<%f>\n, 1234.56 ); printf( "<%e>\n, 1234.56 );
printf( "<%4.2f>\n, 1234.56 ); printf( "<%3.1f>\n,
1234.56 ); printf( "<%10.3f>\n, 1234.56 ); printf(
"<%10.3e>\n, 1234.56 ); return 0; }

CHAPTER 3. C INPUT & OUTPUT


are comma-separated and swallow the comma when it is
encountered.
If a format code is preceded with an asterisk, the data will
be read and discarded. For example, if the example were
changed to:

-- prints:

scanf( "%d%*c%s, &val, name );


<1234.560000> <1.234560e+03> <1234.56> <1234.6> -- then if the two elds were separated by a ":", that char< 1234.560> < 1.234e+03>
acter would be read in and discarded.
And nally:
The scanf()" function will return the value EOF (an
/* prtstr.c */ #include <stdio.h> int main(void) { printf(
"<%2s>\n, Barney must die!" ); printf( "<%22s>\n,
Barney must die!" ); printf( "<%22.5s>\n, Barney
must die!" ); printf( "<%22.5s>\n, Barney must die!"
); return 0; }

int), dened in stdio.h, when its input is terminated.


The putchar()" and getchar()" functions handle single
character I/O. For example, the following program accepts characters from standard input one at a time:

/* inout.c */ #include <stdio.h> int main (void) { unsigned int ch; while ((ch = getchar()) != EOF) { putchar(
<Barney must die!> < Barney must die!> < Barne> ch ); } return 0; }
<Barne >
The getchar function returns an int and also termi-- prints:

Just for convenience, the table of special characters listed nates with an EOF. Notice the neat way C allows a proin chapter 2 is repeated here. These characters can be gram to get a value and then test it in the same expression,
embedded in printf strings:
a particularly useful feature for handling loops.
'\a' alarm (beep) character '\p' backspace '\f' formfeed '\n'
newline '\r' carriage return '\t' horizontal tab '\v' vertical
tab '\\' backslash '\?' question mark '\'' single quote '\"'
double quote '\0NN' character code in octal '\xNN' character code in hex '\0' null character

One word of warning on single-character I/O: if a program is reading characters from the keyboard, most operating systems won't send the characters to the program
until the user presses the Enter key, meaning its not
possible to perform single-character keyboard I/O this
The scanf()" function reads formatted data using a syn- way.
tax similar to that of printf, except that it requires point- The little program above is the essential core of a
ers as parameters, since it has to return values. For ex- character-mode text lter, a program that can perform
ample:
some transformation between standard input and standard output. Such a lter can be used as an element to
/* cscanf.c */ #include <stdio.h> int main(void) { int val;
char name[256]; printf( Enter your age and name.\n ); construct more sophisticated applications:
scanf( "%d %s, &val, name ); printf( Your name is: %s type le.txt > lter1 | lter2 > outle.txt
-- and your age is: %d\n, name, val ); return 0; }
The following lter capitalizes the rst character in each
There is no "&" in front of name since the name of a word in the input. The program operates as a state mastring is already a pointer. Input elds are separated by chine, using a variable that can be set to dierent valwhitespace (space, tab, or newline), though a count, for ues, or states, to control its operating mode. It has two
example "%10d, can be included to dene a specic eld states: SEEK, in which it is looking for the rst characwidth. Formatting codes are the same as for printf()", ter, and REPLACE, in which it is looking for the end of
except:
a word.
There is no "%g format code.
The "%f and "%e format codes work the same.

In SEEK state, it scans through whitespace (space, tab, or


newline), echoing characters. If it nds a printing character, it converts it to uppercase and goes to REPLACE
state. In REPLACE state, it converts characters to lowercase until it hits whitespace, and then goes back to SEEK
state.

There is a "%h format code for reading short inteThe program uses the tolower()" and toupper()" funcgers.
tions to make case conversions. These two functions will
If characters are included in the format code, scanf()" be discussed in the next chapter.
will read in the characters and discard them. For example, /* caps.c */ #include <stdio.h> #include <ctype.h> #deif the example above were modied as follows:
ne SEEK 0 #dene REPLACE 1 int main(void) { int ch,
state = SEEK; while(( ch = getchar() ) != EOF ) { switch(
scanf( "%d,%s, &val, name );
state ) { case REPLACE: switch( ch ) { case ' ': case '\t':
-- then scanf()" will assume that the two input values

3.2. C FILE-IO THROUGH LIBRARY FUNCTIONS

17

case '\n': state = SEEK; break; default: ch = tolower( ch


); break; } break; case SEEK: switch( ch ) { case ' ': case
'\t': case '\n': break; default: ch = toupper( ch ); state =
REPLACE; break; } } putchar( ch ); } return 0; }

Rename a le. remove() Delete a le. fprintf() Formatted write. fscanf() Formatted read. fwrite() Unformatted
write. fread() Unformatted read. putc() Write a single
byte to a le. getc() Read a single byte from a le. fputs()
The puts()" function is like a simplied version of Write a string to a le. fgets() Read a string from a le.
printf()" without format codes. It prints a string that is All these library functions depend on denitions made in
automatically terminated with a newline:
the stdio.h header le, and so require the declaration:
puts( Hello world!" );

#include <stdio.h>

The fgets()" function is particularly useful: it allows C documentation normally refers to these functions as
reads a line of text terminated by a newline. It is much performing stream I/O, not le I/O. The distinction is
less nicky about its inputs than scanf()":
that they could just as well handle data being transferred
/* cgets.c */ #include <stdio.h> #include <string.h> #in- through a modem as a le, and so the more general term
clude <stdlib.h> int main(void) { char word[256], *guess data stream is used rather than le. However, we'll
stay with the le terminology in this document for the
= blue\n"; int i, n = 0; puts( Guess a color (use lower
case please):" ); while( fgets(word, 256, stdin) != NULL sake of simplicity.
) { if( strcmp( word, guess ) == 0 ) { puts( You win!" ); The fopen()" function opens and, if need be, creates a
le. Its syntax is:
break; } else { puts( No, try again. ); } } return 0; }
This program includes the strcmp function, which per- <le pointer> = fopen( <lename>, <access mode> );
forms string comparisons and returns 0 on a match. This The fopen()" function returns a le pointer, declared
function is described in more detail in the next chapter.
as follows:
These functions can be used to implement lters that opFILE *<le pointer>;
erate on lines of text, instead of characters. A core proThe le pointer will be returned with the value NULL, degram for such lters follows:
ned in stdio.h, if there is an error. The access modes
/* llter.c */ #include <stdio.h> int main (void) { char are dened as follows:
b[256]; while (( gets( b ) ) != NULL ) { puts( b ); } return
r Open for reading. w Open and wipe (or create) for writ0; }
ing. a Append -- open (or create) to write to end of le. r+
The fgets()" function returns NULL, dened in Open a le for reading and writing. w+ Open and wipe
stdio.h, on input termination or error.
(or create) for reading and writing. a+ Open a le for
The Windows-based console-I/O functions getch()" and reading and appending.
getche()" operate much as getchar()" does, except that
The lename is simply a string of characters.
getche()" echoes the character automatically.
It is often useful to use the same statements to communiThe kbhit()" function is very dierent in that it only indi- cate either with les or with standard I/O. For this reason,
cates if a key has been pressed or not. It returns a nonzero the stdio.h header le includes predened le pointers
value if a key has been pressed, and zero if it hasn't. This with the names stdin and stdout. Theres no 't need
allows a program to poll the keyboard for input, instead of to do an fopen()" on them -- they can just be assigned to
hanging on keyboard input and waiting for something to a le pointer:
happen. As mentioned, these functions require the cofpin = stdin; fpout = stdout;
nio.h header le, not the stdio.h header le.

3.2 C File-IO Through Library


Functions

-- and any following le-I/O functions won't know the difference.


The fclose()" function simply closes the le given by its
le pointer parameter. It has the syntax:
fclose( fp );
The fseek()" function call allows the byte location in a
le to be selected for reading or writing. It has the syntax:

The le-I/O library functions are much like the consoleI/O functions. In fact, most of the console-I/O functions fseek( <le_pointer>, <oset>, <origin> );
can be thought of as special cases of the le-I/O functions. The oset is a long and species the oset into the le,
The library functions include:
in bytes. The origin is an int and is one of three stanfopen() Create or open a le for reading or writing. dard values, dened in stdio.h":
fclose() Close a le after reading or writing it. fseek() SEEK_SET Start of le. SEEK_CUR Current location.
Seek to a certain location in a le. rewind() Rewind a SEEK_END End of le.
le back to its beginning and leave it open. rename()

18

CHAPTER 3. C INPUT & OUTPUT

The fseek()" function returns 0 on success and non-zero


on failure.

The "%f and "%e format codes work the same.

The rewind()", rename()", and remove()" functions


are straightforward. The rewind()" function resets an
open le back to its beginning. It has the syntax:

There is a "%h format code for reading short integers.

Numeric modiers can be used, of course. The fscanf()"


function returns the number of items that it successfully
The rename()" function changes the name of a le:
read, or the EOF code, an int, if it encounters the end
rename(
<old_le_name_string>, of the le or an error.
<new_le_name_string> );
The following program demonstrates the use of
rewind( <le_pointer> );

The remove()" function deletes a le:

fprintf()" and fscanf()":

remove( <le_name_string> )

/* fprsc.c */ #include <stdio.h> void main() { int ctr, i[3],


n1 = 16, n2 = 256; oat f[4], n3 = 3.141592654f; FILE
*fp; fp = fopen( data, w+" ); /* Write data in: decimal integer formats decimal, octal, hex integer formats
oating-point formats */ fprintf( fp, "%d %10d %10d
\n, n1, n1, n1 ); fprintf( fp, "%d %o %x \n, n2, n2, n2
); fprintf( fp, "%f %10.10f %e %5.4e \n, n3, n3, n3, n3
); /* Rewind le. */ rewind( fp ); /* Read back data. */
puts( "" ); fscanf( fp, "%d %d %d, &i[0], &i[1], &i[2] );
printf( " %d\t%d\t%dn, i[0], i[1], i[2] ); fscanf( fp, "%d
%o %x, &i[0], &i[1], &i[2] ); printf( " %d\t%d\t%d\n,
i[0], i[1], i[2] ); fscanf( fp, "%f %f %f %f, &f[0],
&f[1], &f[2], &f[3] ); printf( " %f\t%f\t%f\t%f\n, f[0],
f[1], f[2], f[3] ); fclose( fp ); }

The fprintf()" function allows formatted ASCII data output to a le, and has the syntax:
fprintf( <le pointer>, <string>, <variable list> );
The fprintf()" function is identical in syntax to printf()",
except for the addition of a le pointer parameter. For
example, the fprintf()" call in this little program:
/* fprpi.c */ #include <stdio.h> void main() { int n1 = 16;
oat n2 = 3.141592654f; FILE *fp; fp = fopen( data,
w ); fprintf( fp, " %d %f, n1, n2 ); fclose( fp ); }
-- stores the following ASCII data:
16 3.14159

The program generates the output:


The formatting codes are exactly the same as for
16 16 16 256 256 256 3.141593 3.141593 3.141593
printf()":
3.141600
%d decimal integer %ld long decimal integer %c character %s string %e oating-point number in exponential no- The fwrite()" and fread()" functions are used for binary
tation %f oating-point number in decimal notation %g le I/O. The syntax of fwrite()" is as follows:
use %e and %f, whichever is shorter %u unsigned deci- fwrite( <array_pointer>, <element_size>, <count>,
mal integer %o unsigned octal integer %x unsigned hex <le_pointer> );
integer
The array pointer is of type void, and so the array can
Field-width speciers can be used as well. The fprintf()" be of any type. The element size and count, which give
function returns the number of characters it dumps to the the number of bytes in each array element and the number
le, or a negative number if it terminates with an error.
of elements in the array, are of type size_t, which are
The fscanf()" function is to fprintf()" what scanf()" is equivalent to unsigned int.
to printf()": it reads ASCII-formatted data into a list of The fread()" function similarly has the syntax:
variables. It has the syntax:
fread( <array_pointer>, <element_size>, <count>,
fscanf( <le pointer>, <string>, <variable list> );
<le_pointer> );
However, the string contains only format codes, no text, The fread()" function returns the number of items it acand the variable list contains the addresses of the vari- tually read.
ables, not the variables themselves. For example, the program below reads back the two numbers that were stored The following program stores an array of data to a le and
then reads it back using fwrite()" and fread()":
with fprintf()" in the last example:
/* frdata.c */ #include <stdio.h> void main() { int n1; oat /* fwrrd.c */ #include <stdio.h> #include <math.h> #den2; FILE *fp; fp = fopen( data, r ); fscanf( fp, "%d ne SIZE 20 void main() { int n; oat d[SIZE]; FILE *fp;
%f, &n1, &n2 ); printf( "%d %f, n1, n2 ); fclose( fp ); for( n = 0; n < SIZE; ++n ) /* Fill array with roots. */ {
d[n] = (oat)sqrt( (double)n ); } fp = fopen( data, w+"
}
); /* Open le. */ fwrite( d, sizeof( oat ), SIZE, fp ); /*
The fscanf()" function uses the same format codes as Write it to le. */ rewind( fp ); /* Rewind le. */ fread(
fprintf()", with the familiar exceptions:
d, sizeof( oat ), SIZE, fp ); /* Read back data. */ for(
n = 0; n < SIZE; ++n ) /* Print array. */ { printf( "%d:
There is no "%g format code.
%7.3f\n, n, d[n] ); } fclose( fp ); /* Close le. */ }

3.3. C FILE-IO THROUGH SYSTEM CALLS

19

The putc()" function is used to write a single character fcntl.h":


to an open le. It has the syntax:
#include <fcntl.h>
putc( <character>, <le pointer> );
The creat()" system call, of course, creates a le. It has
The getc()" function similarly gets a single character the syntax:
from an open le. It has the syntax:
<le descriptor variable> = creat( <lename>, <protec<character variable> = getc( <le pointer> );

tion bits> );

The getc()" function returns EOF on error. The con- This system call returns an integer, called a le descripsole I/O functions putchar()" and getchar()" are really tor, which is a number that identies the le generated
only special cases of putc()" and
by creat()". This number is used by other system calls in
the program to access the le. Should the creat()" call
getc()" that use standard output and input.
encounter an error, it will return a le descriptor value of
The fputs()" function writes a string to a le. It has the 1.
syntax:
The lename parameter gives the desired lename for
fputs( <string / character array>, <le pointer> );
the new le. The permission bits give the access
The fputs()" function will return an EOF value on error. rights to the le. A le has three
For example:
permissions associated with it:
fputs( This is a test, fptr );
Write permission:
The fgets()" function reads a string of characters from a
le. It has the syntax:
Allows data to be written to the le.
fgets( <string>, <max_string_length>, <le_pointer> );
Read permission:
The fgets function reads a string from a le until if nds
a newline or grabs <string_length-1> characters. It will
return the value NULL on an error.
Allows data to be read from the le.
The following example program simply opens a le and
copies it to another le, using fgets()" and fputs()":

Execute permission:

/* fcopy.c */ #include <stdio.h> #dene MAX 256 void


main() { FILE *src, *dst; char b[MAX]; /* Try to open Designates that the le is a program that can be run.
source and destination les. */ if ( ( src = fopen( in- These permissions can be set for three dierent levels:
le.txt, r )) == NULL ) { puts( Can't open input le.
); exit(); } if ( (dst = fopen( outle.txt, w )) == NULL
User level:
) { puts( Can't open output le. ); fclose( src ); exit(); }
/* Copy one le to the next. */ while( ( fgets( b, MAX,
Permissions apply to individual user.
src ) ) != NULL ) { fputs( b, dst ); } /* All done, close up
shop. */ fclose( src ); fclose( dst ); }
Group level:

3.3 C File-IO Through System


Calls

Permissions apply to members of users dened group.


System level:
Permissions apply to everyone on the system.

For the creat()" system call, the permissions are exFile-I/O through system calls is simpler and operates at pressed in octal, with an octal digit giving the three pera lower level than making calls to the C le-I/O library. mission bits for each level of permissions. In octal, the
permission settings:
There are seven fundamental le-I/O system calls:
0644
creat() Create a le for reading or writing. open() Open a
le for reading or writing. close() Close a le after read- -- grant read and write permissions for the user, but only
ing or writing. unlink() Delete a le. write() Write bytes read permissions for group and system. The following
to le. read() Read bytes from le.
octal number gives all permissions to everyone:
These calls were devised for the UNIX operating system 0777
and are not part of the ANSI C spec.
An attempt to creat()" an existing le (for which the proUse of these system calls requires a header le named gram has write permission) will not return an error. It will

20

CHAPTER 3. C INPUT & OUTPUT

instead wipe the contents of the le and return a le de- write( <le descriptor>, <buer>, <buer length> );
scriptor for it.
The le descriptor is returned by a creat()" or open()"
For example, to create a le named data with read and system call. The buer is a pointer to a variable or an
write permission for everyone on the system would re- array that contains the data; and the buer length gives
quire the following statements:
the number of bytes to be written into the le.
#dene RD_WR 0666 ... int fd; /Dene le descriptor. While dierent data types may have dierent byte lengths
*/ fd = creat( data, RD_WR );
on dierent systems, the sizeof()" statement can be used
The open()" system call opens an existing le for reading to provide the proper buer length in bytes. A write()"
call could be specied as follows:
or writing. It has the syntax:
<le descriptor variable> = open( <lename>, <access oat array[10]; ... write( fd, array, sizeof( array ) );
The write()" function returns the number of bytes it acmode> );
tually writes. It will return 1 on an error.
The open()" call is similar to the creat()" call in that it
returns a le descriptor for the given le, and returns a The read()" system call reads data from a open le. Its
le descriptor of 1 if it encounters an error. However, syntax is exactly the same as that of the write()" call:
the second parameter is an access mode, not a permis- read( <le descriptor>, <buer>, <buer length> );
sion code. There are three modes (dened in the fcntl.h
The read()" function returns the number of bytes it actuheader le):
ally returns. At the end of le it returns 0, or returns 1
O_RDONLY Open for reading only. O_WRONLY on error.
Open for writing only. O_RDWR Open for reading and
writing.
For example, to open data for writing, assuming that the
le had been created by another program, the following
statements would be used:
int fd; fd = open( data, O_WRONLY );
A few additional comments before proceeding:
A creat()" call implies an open()". There is no
need to creat()" a le and then open()" it.
There is an operating-system-dependent limit on the
number of les that a program can have open at any
one time.
The le descriptor is no more than an arbitrary number that a program uses to distinguish one open le
for another. When a le is closed, re-opening it
again will probably not give it the same le descriptor.
The close()" system call is very simple. All it does is
close()" an open le when there is no further need to
access it. The close()" system call has the syntax:
close( <le descriptor> );
The close()" call returns a value of 0 if it succeeds, and
returns 1 if it encounters an error.
The unlink()" system call deletes a le. It has the syntax:
unlink( <le_name_string> );
It returns 0 on success and 1 on failure. Note: Even
after unlink, you will be able to read / write using fd.
The write()" system call writes data to an open le. It
has the syntax:

Chapter 4

C Library Functions & Other Comments


4.1 C Math Library

4.2 C Standard Utility Library &


Time Library

This chapter discusses some useful standard C libraries:


The utility functions library features a grab-bag of functions. It requires the declaration:

math library

#include <stdlib.h>

standard utility library

Useful functions include:

the sprintf()" function

command-line arguments

atof( <string> ) Convert numeric string to double value.


atoi( <string> ) Convert numeric string to int value. atol(
<string> ) Convert numeric string to long value. rand()
Generates pseudorandom integer. srand( <seed> ) Seed
random-number generator -- seed is an int. exit(
<status> ) Exits program -- status is an int. system( <string> ) Tells system to execute program given
by string. abs( n ) Absolute value of int argument.
labs( n ) Absolute value of long-int argument.

dynamic memory allocation

The functions atof()", atoi()", and atol()" will return 0


if they can't convert the string given them into a value.

pointers to functions
PC memory model and other declarations

The time and date library includes a wide variety of functions, some of them obscure and nonstandard. This library requires the declaration:

troubleshooting hints

#include <time.h>

string function library


character class test library
And the following minor topics:

The most essential function is time()", which returns the


number of seconds since midnight proleptic Coordinated
Universal Time (UTC) of January 1, 1970, not counting
leap seconds. It returns a value as time_t (a long) as
dened in the header le.

The math library requires the declaration:


#include <math.h>
The math functions consist of:
sin( x ) Sine of x. cos( x ) Cosine of x. tan( x ) Tangent of
x. asin( x ) Inverse sine of x. acos( x ) Inverse cosine of x.
atan( x ) Inverse tangent of x. sinh( x ) Hyperbolic sine of
x. cosh( x ) Hyperbolic cosine of x. tanh( x ) Hyperbolic
tangent of x. exp( x ) Exponential function -- e^x. log( x
) Natural log of x. log10( x ) Base 10 log of x. pow( x, y
) Power function -- x^y. sqrt( x ) Square root of x. ceil(
x ) Smallest integer not less than x, returned as double.
oor( x ) Greatest integer not greater than x, returned as
double. fabs( x ) Absolute value of x.

The following function uses time()" to implement a program delay with resolution in seconds:
/delay.c */ #include <stdio.h> #include <time.h> void
sleep( time_t delay ); void main() { puts( Delaying for
3 seconds. ); sleep( 3 ); puts( Done!" ); } void sleep(
time_t delay ) { time_t t0, t1; time( &t0 ); do { time( &t1
); } while (( t1 - t0 ) < delay ); }

The ctime()" function converts the time value returned


by time()" into a time-and-date string. The following
All values are doubles, and trig values are expressed in little program prints the current time and date:
/time.c */ #include <stdio.h> #include <time.h> void
radians.
21

22

CHAPTER 4. C LIBRARY FUNCTIONS & OTHER COMMENTS

main() { time_t *t; time( t ); puts( ctime( t )); }


This program prints a string of the form:

strcmp() Compare two strings. strchr() Find character


in string. strstr() Find string in string. strlwr() Convert
string to lowercase. strupr() Convert string to uppercase.

Tue Dec 27 15:18:16 1994

4.2.1

further reading

C Programming/Standard libraries
C Programming/C Reference
C++ Programming/Code/Standard C Library

4.3 The C sprintf Function

strlen()
The strlen()" function gives the length of a string, not
including the NUL character at the end:
/* strlen.c */ #include <stdio.h> #include <string.h> int
main() { char *t = XXX"; printf( Length of <%s> is
%d.\n, t, strlen( t )); }
This prints:
Length of <XXX> is 3.

strcpy()
The sprintf function creates strings with formatted data.
Technically speaking, this is part of the standard-I/O li- The strcpy function copies one string from another. For
brary, and requires the declaration:
example:
#include <stdio.h>
/* strcpy.c */ #include <stdio.h> #include <string.h> int
main() { char s1[100], s2[100]; strcpy( s1, xxxxxx 1
However, it is really a string function and needs to be dis- ); strcpy( s2, zzzzzz 2 ); puts( Original strings: " );
cussed along with the other string functions. The syntax puts( "" ); puts( s1 ); puts( s2 ); puts( "" ); strcpy( s2, s1
of sprintf()" is exactly the same as it is for printf()", ex- ); puts( New strings: " ); puts( "" ); puts( s1 ); puts( s2 ); }
cept there is an extra parameter at the beginning, which
is a pointer to a string. Instead of outputting to standard This will print:
output, sprintf outputs to the string. For example:
Original strings: xxxxxx 1 zzzzzz 2 New strings: xxxxxx
/* csprntf.c */ #include <stdio.h> int main() { char 1 xxxxxx 1
b[100]; int i = 42; oat f = 1.1234f; sprintf( b, FormatPlease be aware of two features of this program:
ted data: %d / %f, i, f ); puts( b ); }
-- prints the string:
Formatted data: 42 / 1.1234
There is also an sscanf()" function that similarly mirrors
scanf()" functionality.

4.3.1

C STRING FUNCTION LIBRARY

moved to A Little C Primer/C String Function Library

4.4 C String Function Library

The string-function library requires the declaration:


#include <string.h>
The most important string functions are as follows:

This program assumes that s1 has enough space to


store the nal string. The strcpy()" function won't
bother to check, and will give erroneous results if
that is not the case.
A string constant can be used as the source string
instead of a string variable. Using a string constant
for the destination, of course, makes no sense.
These comments are applicable to most of the other string
functions.
strncpy()
There is a variant form of strcpy named strncpy that
will copy n characters of the source string to the destination string, presuming there are that many characters
available in the source string. For example, if the following change is made in the example program:
strncpy( s2, s1, 5 );

strlen() Get length of a string. strcpy() Copy one string to


another. strcat() Link together (concatenate) two strings. -- then the results change to:

4.4. C STRING FUNCTION LIBRARY


New strings: xxxxxx 1 xxxxxz 2

23
A stricmp()" function that ignores case in comparisons.

Notice that the parameter n is declared size_t, which


is dened in string.h. Because strncpy does not add '\0'
after coping 5 charecters
strnicmp()
strcat()

A case-insensitive version of strncmp called strnicmp.

The strcat()" function joins two strings:


/* strcat.c */ #include <stdio.h> #include <string.h> int strchr()
main() { char s1[50], s2[50]; strcpy( s1, Tweedledee "
); strcpy( s2, Tweedledum ); strcat( s1, s2 ); puts( s1 ); } The strchr function nds the rst occurrence of a character in a string. It returns a pointer to the character if it
nds it, and null if not. For example:
This prints:
Tweedledee Tweedledum
strncat()

/* strchr.c */ #include <stdio.h> #include <string.h> int


main() { char *t = "MEAS:VOLT:DC?"; char *p; p = t;
puts( p ); while(( p = strchr( p, ':' )) != NULL ) { puts(
++p ); } }

There is a variant version of strcat()" named strncat()" This prints:


that will append n characters of the source string to the
destination string. If the example above used strncat()" MEAS:VOLT:DC? VOLT:DC? DC?
with a length of 7:
The character is dened as a character constant, which
C regards as an int. Notice how the example program
strncat( s1, s2, 7 );
increments the pointer before using it ("++p) so that it
doesn't point to the ":" but to the character following it.
-- the result would be:
Tweedledee Tweedle
Again, the length parameter is of type size_t.

strrchr() The strrchr()" function is almost the same as


strchr()", except that it searches for the last occurrence
of the character in the string.

strcmp()
The strcmp()" function compares two strings:
/* strcmp.c */ #include <stdio.h> #include <string.h>
#dene ANSWER blue int main() { char t[100]; puts(
What is the secret color?" ); gets( t ); while ( strcmp( t,
ANSWER ) != 0 ) { puts( Wrong, try again. ); gets( t
); } puts( Right!" ); }

strstr()
The strstr()" function is similar to strchr()" except that it
searches for a string, instead of a character. It also returns
a pointer:
char *s = Black White Brown Blue Green"; ... puts(
strstr( s, Blue ) );

The strcmp()" function returns a 0 for a successful comparison, and nonzero otherwise. The comparison is casestrlwr() and strupr()
sensitive, so answering BLUE or Blue won't work.
There are three alternate forms for strcmp()":
strncmp()

The strlwr()" and strupr()" functions simply perform


lowercase or uppercase conversion on the source string.
For example:

/* casecvt.c */ #include <stdio.h> #include <string.h>


A strncmp()" function which, as might be guessed, int main() { char *t = Hey Barney hey!"; puts( strlwr( t
compares n characters in the source string with the ) ); puts( strupr( t ) ); }
destination string:
-- prints:
strncmp( s1, s2, 6 )".
hey barney hey! HEY BARNEY HEY!
stricmp()

These two functions are only implemented in some compilers and are not part of ANSI C.

24

CHAPTER 4. C LIBRARY FUNCTIONS & OTHER COMMENTS

further reading
C Programming/Strings
C++ Programming/Code/IO/Streams/string

4.5 C Character Class Test Library

stooges moe larry curley


-- the output is:
stooges moe larry curley
In practice, the command line will probably take a number of arguments, some of which will indicate options
or switches, designated by a leading "-" or "/". Some of
the switches may be specied separately or together, and
some may accept an associated parameter. Other arguments will be text strings, giving numbers, le names, or
other data.

These functions perform various tests on characters. The following example program demonstrates parsing the
command-line arguments for an arbitrary program. It asThey require the declaration:
sumes that the legal option characters are A, B, C,
#include <ctype.h>
and S, in either upper- or lower-case. The S option
The character is represented as an int and the functions must be followed by some string representing a paramereturn an int. They return 0 if the test is false and non-0 ter.
if the test is true:
/* cparse.c */ #include <stdio.h> #include <stdlib.h> #inisalnum( c ) Character is alpha or digit. isalpha( c ) Char- clude <string.h> main( int argc, char *argv[] ) { int m, n,
acter is alpha. iscntrl( c ) Character is control character. /* Loop counters. */ l, /* String length. */ x, /* Exit
isdigit( c ) Character is decimal digit. isgraph( c ) Char- code. */ ch; /* Character buer. */ char s[256]; /* String
acter is printing character (except space). islower( c ) buer. */ for( n = 1; n < argc; n++ ) /* Scan through
Character is lower-case. isprint( c ) Character is print- args. */ { switch( (int)argv[n][0] ) /* Check for option
ing character (including space). ispunct( c ) Character character. */ { case '-': case '/': x = 0; /* Bail out if 1.
is printing character but not space/alpha-digit. isspace( */ l = strlen( argv[n] ); for( m = 1; m < l; ++m ) /* Scan
c ) Character is space, FF, LF, CR, HT, VT. isupper( c through options. */ { ch = (int)argv[n][m]; switch( ch ) {
) Character is upper-case. isxdigit( c ) Character is hex case 'a': /* Legal options. */ case 'A': case 'b': case 'B':
digit.
case 'C': case 'd': case 'D': printf( Option code = %c\n,
The library also contains two conversion functions that ch ); break; case 's: /* String parameter. */ case 'S': if(
m + 1 >= l ) { puts( Illegal syntax -- no string!" ); exit(
also accept and return an int":
1 ); } else { strcpy( s, &argv[n][m+1] ); printf( String =
tolower( c ) Convert to lower case. toupper( c ) Convert %s\n, s ); } x = 1; break; default: printf( Illegal option
to upper case.
code = %c\n, ch ); x = 1; /* Not legal option. */ exit( 1
); break; } if( x == 1 ) { break; } } break; default: printf(
Text = %s\n, argv[n] ); /* Not option -- text. */ break;
4.6 C Command Line Arguments } } puts( DONE!" ); }
For a more practical example, heres a simple program,
based on an example from the previous chapter, that attempts to read the names of an input and output le from
C allows a program to obtain the command line argu- the command line. If no les are present, it uses standard
ments provided when the executable is called, using two input and standard output instead. If one le is present, it
optional parameters of main()" named argc (argument is assumed to be the input le and opens up standard output. This is a useful template for simple le-processing
count)" and argv (argument vector)".
programs.
The argc variable gives the count of the number of
command-line parameters provided to the program. This /* cple.c */ #include <stdio.h> #include <stdlib.h> #decount includes the name of the program itself, so it will ne MAX 256 void main( unsigned int argc, unsigned
always have a value of at least one. The argv variable is char *argv[] ) { FILE *src, *dst; char b[MAX]; /* Try to
a pointer to the rst element of an array of strings, with open source and destination les. */ switch (argc) { case
each element containing one of the command-line argu- 1: /* No parameters, use stdin-stdout. */ src = stdin; dst
= stdout; break; case 2: /* One parameter -- use input le
ments.
& stdout. */ if ( ( src = fopen( argv[1], r )) == NULL
The following example program demonstrates:
) { puts( Can't open input le.\n ); exit( 0 ); } dst =
/* cmdline.c */ #include <stdio.h> void main( int argc, stdout; break; case 3: /* Two parameters -- use input and
char *argv[] ) { int ctr; for( ctr=0; ctr < argc; ctr++ ) { output les. */ if ( ( src = fopen( argv[1], r )) == NULL
) { puts( Can't open input le.\n ); exit( 0 ); } if ( ( dst
puts( argv[ctr] ); } }
= fopen( argv[2], w )) == NULL ) { puts( Can't open
If this program is run from the command line as follows:

4.8. C DYNAMIC MEMORY ALLOCATION & DEALLOCATION

25

output le.\n ); exit( 0 ); } break; default: /* Too many


parameters. */ puts( Wrong parameters.\n ); exit( 0 );
} /* Copy one le to the next. */ while( ( fgets( b, MAX,
src ) ) != NULL ) { fputs( b, dst ); } /* All done, close up
shop. */ fclose( src ); fclose( dst ); }

In more sophisticated programs, this leads to trouble.


There may be no way of knowing how big an array needs
to be for the specic task the program is performing, and
so allocating an array in a xed size will either result in
wasted memory or in not having enough to do the job.

4.7 Pointers to C Functions

The answer to this problem is to have the program allocate


the memory at runtime, and thats what the malloc()"
library function does. For example, lets use malloc()"
to allocate an array of char":

This document has explained how to declare pointers to


variables, arrays, and structures in C. It is also possible to
dene pointers to functions. This feature allows functions
to be passed as arguments to other functions. This is useful for, say, building a function that determines solutions
to a range of math functions.

/*malloc.c */ #include <stdio.h> #include <stdlib.h>


/*For malloc, exit functions. */ int main() { char *p;
/*Pointer to array. */ unsigned count; /*Size of array. */
puts( Size of array?" ); scanf( "%d, &count ); /*Get
size in bytes. */ p = malloc( (size_t)count ); /*Allocate
array. */ if( p == NULL ) /*Check for failure. */ { puts(
Can't allocate memory!" ); exit( 0 ); } puts( Allocated
array!" ); free( p ); /*Release memory. */ return 0; }

The syntax for declaring pointers to functions is obscure, The header le stdlib.h must be included, and a pointer
and so lets start with an idiot example: declaring a pointer to the memory block to be allocated must be declared.
The malloc()" function sets the pointer to the allocated
to the standard library function printf()":
memory block with:
/* ptrprt.c */ #include <stdio.h> void main() { int
(*func_ptr) (); /* Declare the pointer. */ func_ptr = p = malloc( (size_t)count );
printf; /* Assign it a function. */ (*func_ptr) ( Printf is The count is in bytes and it is cast to the type of size_t,
here!\n ); /* Execute the function. */ }
which is dened in stdlib.h. The pointer returned by
malloc()" is assigned to the variable p, which is of type
The function pointer has to be declared as the same type char *". In ANSI C, malloc()" returns a pointer of type
void *", which can be assigned to any other pointer type
(int in this case) as the function it represents.
without a cast.
Next, lets pass function pointers to another function.
This function will assume the functions passed to it are If the malloc()" fails because it can't allocate the memmath functions that accept double and return double val- ory, it returns the value NULL (as dened in stdio.h).
ues:
It is simple to allocate other data types:
/* ptrroot.c */ #include <stdio.h> #include <math.h> int *buf; ... buf = malloc( (size_t)sizeof( int ) );
void testfunc ( char *name, double (*func_ptr) () ); void
main() { testfunc( square root, sqrt ); } void testfunc The sizeof()" function is used to determine the number
( char *name, double (*func_ptr) () ) { double x, xinc; of bytes in the int data type.
int c; printf( Testing function %s:\n\n, name ); for( When the programs nished using the memory block, it
c=0; c < 20; ++c ) { printf( "%d: %f\n, c,(*func_ptr)( get rids of it using the free function:
(double)c )); } }
free( p );
C also contains two other memory-allocation functions
It is obvious that not all functions can be passed to testclosely related to malloc()": the calloc()" function,
func()". The function being passed must agree with the
which performs the same function as malloc()" but alexpected number and type of parameters, as well as with
lows the block allocated to be specied in terms of numthe value returned.
ber of elements:

4.8 C Dynamic Memory Allocation


& Deallocation

void *calloc( size_t <number_elements>,


<sizeof_element_type> );

-- and the realloc()" function, which reallocates the size


of an array thats already been allocated:
void *realloc( void
<size_in_bytes> );

For simple programs, it is OK to just declare an array of


a given size:
char buer[1024]

size_t

*<block_pointer>,

size_t

26

CHAPTER 4. C LIBRARY FUNCTIONS & OTHER COMMENTS

4.9 Common Programming Problems in C

This means that a string will always be one character bigger than the text it stores. It can also cause trouble if a
string is being created on a character-by-character basis,
and the program doesn't tack the null character onto the
end of it.

There are a number of common programming pitfalls in 9: Failing to allocate enough memory for a string -- or, if
pointers are declared, to allocate any memory for it at all.
C that even trap experienced programmers:
1: Confusing "=" (assignment operator) with "==" 10: Failing to check return values from library functions.
Most library functions return an error code; while it may
(equality operator). For example:
not be desirable to check every invocation of printf()",
if ( x = 1 ){ /* wrong! */ } ... if ( x == 1 ){ /* good. */ } be careful not to ignore error codes in critical operations.
and
Of course, forgetting to store the value returned by a funcfor ( x == 1; ... /* wrong! */ ... for ( x = 1; ... /* good. */ tion when thats the only way to get the value out of it is a
bonehead move, but people do things like that every now
2: Confusing precedence of operations in expressions.
and then.
When in doubt, use parentheses to enforce precedence.
11: Having duplicate library-function names. The comIt never hurts to use a few extra parenthesis.
piler will not always catch such bugs.
3: Confusing structure-member operators. If struct_val
is a structure and struct_ptr is a pointer to a structure, 12: Forgetting to specify header les for library functions.
then:
13: Specifying variables as parameters to functions when
struct_val->myname
-- is wrong and so is:

pointers are supposed to be specied, and the reverse.


If the function returns a value through a parameter, that
means it must be specied as a pointer:

struct_ptr.myname

myfunc( &myvar );
4: Using incorrect formatting codes for printf()" and
The following will not do the job:
scanf()". Using a "%f to print an int, for example,
myfunc( myvar );
can lead to bizarre output.
5: Remember that the actual base index of an array is 0, Remember that a function may require a pointer as a paand the nal index is 1 less than the declared size. For rameter even if it doesn't return a value, though as a rule
this is not a good programming practice.
example:
int data[20]; ... for ( x = 1; x <= 20; ++x ) { printf( 14: Getting mixed up when using nested if and else
statements. The best way to avoid problems with this is
"%d\n, data[x] ); }
to always use brackets. Avoiding complicated if con-- will give invalid results when x is 20. Since C does
structs is also a good idea; use switch if theres any
not do bounds checking, this one might be hard to catch.
choice in the matter. Using switch is also useful even
6: Muddling syntax for multidimensional arrays. If:
for simple if statements, since it makes it easier to expand the construct if that is necessary.
data[10][10]
data[2][7]

15: Forgetting semicolons -- though the compiler usually


catches this -- or adding one where it isn't supposed to be
-- which it usually doesn't. For example:

-- will select an element in that array. However:

for( x = 1; x < 10; ++x ); { printf( "%d\n, x ) }

data[ 2, 7 ]

-- never prints anything.

-- is a two-dimensional array, then:

-- will give invalid results but not be agged as an error 16: Forgetting break statements in switch constructs.
by C.
As commented earlier, doing so will simply cause execu7: Confusing strings and character constants. The follow- tion to ow from one clause of the switch to the next.
ing is a string:
17: Careless mixing and misuse of signed and unsigned
values, or of dierent data types. This can lead to some
Y
insanely subtle bugs. One particular problem to watch
-- as opposed to the character constant:
out for is declaring single character variables as unsigned
char. Many I/O functions will expect values of un'Y'
signed int and fail to properly ag EOF. It is recomThis can cause troubles in comparisons of strings against
mended to cast function arguments to the proper type
character constants.
even if it appears that type conversion will take care of
8: Forgetting that strings end in a null character ('\0').

4.9. COMMON PROGRAMMING PROBLEMS IN C


it on its own.
18: Confusion of variable names. It is recommended that
such identiers be unique in the rst 6 characters to ensure
portability of code.
19: In general, excessively tricky and clever code. Programs are nasty beasts and even if it works, it will have
to be modied and even ported to dierent languages.
Maintain a clean structure and do the simple straightforward thing, unless it imposes an unacceptable penalty.

27

Chapter 5

C Quick Reference
5.1 C Quick Reference

character code in hex. '\0' null character.


File-I/O -- #include <stdio.h>:

This section contains a sample program to give syntax examples for fundamental C statements, followed by a list
of library routines. This list is very terse and simply provides reminders. If more details are needed, please refer
to the previous chapters.

FILE *fopen( char *f, char *mode ) != NULL Create or


open le. int fclose( FILE *f ) Close a le. rewind( FILE
*f ) Rewind. rename( char *old, char *new ) Rename a
le. remove( char *name ) Delete a le. fseek( FILE *f,
long oset, int origin) == 0 Seek. fprintf( FILE *f, char
*fmt, <varlist> ) > 0 Formatted write. fscanf( FILE *f,
char *fmt, &<varlist> ) != EOF Formatted read. fwrite(
void *b, size_t s, size_t c, FILE *f ) > 0 Unformatted
write. fread( void *b, size_t s, size_t c, FILE *f ) > 0
Unformatted read. putc( int c, FILE *f ) Write character.
int getc( FILE *f ) != EOF Read character. fputs( char
*s, FILE *f ) Write a string. fgets( char *s, int max, FILE
*f) != NULL Read a string. sprintf( char *b, char *fmt,
<varlist> ) Print into string. sscanf( char *b, char *fmt,
&<varlist> ) > 0 Scan string.

/* sample.c: a silly program to give syntax examples. */


#include <stdio.h> /* Include header le for console I/O.
*/ int f1( int p ); /* Function prototypes. */ long f2( void
); long g; /* Global variable. */ void main( int argc, char
*argv[] ) { oat f; /* Declare variables. */ int ctr; extern
long g; printf( Arguments:\n\n ); for( ctr = 0; ctr < argc;
ctr++ ) { puts( argv[ctr] ); } printf( "\nFunction 1:\n\n
); ctr = 0; while( ctr < 5 ) { printf( "%d\n, f1( ctr++ )
); } printf( "\nFunction 2:\n\n ); ctr = 0; do { g = ctr++;
File modes:
printf( "%d\n, f2( ) ); } while( ctr < 5 ); exit( 0 ); } int
f1( int p ) { return( ( p < 3 ) ? p : p p ); } long f2( void ) r Open for reading. w Open and wipe (or create) for writing. a Append -- open (or create) to write to end of le. r+
{ extern long g; return( g g ); }
Open a le for reading and writing. w+ Open and wipe
Console I/O -- #include <stdio.h>:
(or create) for reading and writing. a+ Open a le for
int printf( char *s, <varlist> ) > 0 Print formatted string reading and appending.
to stdout. int scanf( char *s, *<varlist> ) != EOF Read
Oset values:
formatted data from stdin. int putchar( int ch ) Print a
character to stdout. int getchar() != EOF Read a character SEEK_SET Start of le. SEEK_CUR Current location.
from stdin. int puts( char *s ) Print string to stdout, add SEEK_END End of le.
\n. char *gets() != NULL Read line from stdin (no \n).
Math library -- #include <math.h>:
PC console routines -- #include <conio.h>:
int getch() != 0 Get a character from the keyboard (no
Enter). int getche() != 0 Get a character from the keyboard and echo it. int kbhit() != 0 Check to see if a key
has been pressed.
Format codes:
%h short int (scanf() only) %d decimal integer %ld long
decimal integer %c character %s string %e exponential
oating-point %f decimal oating-point %g use %e or
%f, whichever is shorter (printf() only) %u unsigned decimal integer %o unsigned octal integer %x unsigned hex
integer %10d 10-character eld width. %10d Leftjustied eld. %6.3f 6-character eld width, three digits of precision. '\0NN' character code in octal. '\xNN'

double sin( double x ) Sine of x (in radians). double cos(


double x ) Cosine of x. double tan( double x ) Tangent of
x. double asin( double x ) Inverse sine of x. double acos(
double x ) Inverse cosine of x. double atan( double x )
Inverse tangent of x. double sinh( double x ) Hyperbolic
sine of x. double cosh( double x ) Hyperbolic cosine of x.
double tanh( double x ) Hyperbolic tangent of x. double
exp( double x ) Exponential function -- e^x. double log(
double x ) Natural log of x. double log10( double x )
Base 10 log of x. double pow( double x, double y ) Power
function -- x^y. double sqrt( double x ) Square root of x.
double ceil( double x ) Integer >= x (returned as double).
double oor( double x ) Integer <= x (returned as double).
double fabs( x ) Absolute value of x.

28

5.1. C QUICK REFERENCE


Standard utility library -- #include <stdlib.h>:
double atof( char *nvalstr ) != 0 Convert numeric string
to double. int atoi( char *nvalstr ) != 0 Convert numeric
string to int. long atol( char *nvlastr ) != 0 Convert numeric string to long. int rand() Generates pseudorandom
integer. srand( unsigned seed ) Seed random-number
generator. exit( int status ) Exits program. int system(
char *syscmd ) == 0 Execute system program. int abs(
int n ) Absolute value of int. long labs( long n ) Absolute
value of long.
Time & date library -- #include <time.h>:
time_t time( time_t *timeptr ) Current time count as long
int. char *ctime( time_t *timeptr ) Current time & date
string.
String function library -- #include <string.h>:
int strlen( char *s ) Length. strcpy( char *dst, char *src
) Copy. strncpy( char *dst, char *src, size_t n ) Copy
n characters max. strcat( char *dst, char *s ) Concatenate. strncat( char *d, char *s, size_t n ) Concatenate n
characters. strcmp( char *s1, char *s2 ) == 0 Compare.
strncmp( char *s1, char *s2, size_t n ) == 0 Compare n
characters. stricmp( char *s1, char *s2 ) == 0 Compare,
no case. strnicmp( char *s1, char *s2, size_t n ) == 0
Compare, no case, n chars. char *strchr( char *s, int ch )
!= NULL Find rst character. char *strrchr( char *s, int
ch ) != NULL Find last character. char *strstr( char *dst,
char *src) != NULL Find string. char *strlwr( char *s )
Lowercase. char *strupr( char *s ) Uppercase.
Character class test library -- #include <ctype.h>:
int isalnum( int c ) != 0 Alpha / digit. int isalpha( int c )
!= 0 Alpha. int iscntrl( int c ) != 0 Control character. int
isdigit( int c ) != 0 Decimal digit. int isgraph( int c ) != 0
Printing character (except space). int islower( int c ) != 0
Lower-case. int isprint( int c ) != 0 Printing character (including space). int ispunct( int c ) != 0 Printing character
but not space/alnum. int isspace( int c ) != 0 Space, FF,
LF, CR, HT, VT. int isupper( int c ) != 0 Upper-case. int
isxdigit( int c ) != 0 Hex digit. int tolower( int c ) Convert
to lower case. int toupper( int c ) Convert to upper case.
Dynamic memory allocation -- #include <malloc.h>:
buf = (<type> *)malloc( (size_t)sizeof( <type> ) <array
size>) != NULL free( <type> *buf )

29

Chapter 6

Comments and Revision History


6.1 Comments and Revision History

I wrote this document, not because I am an expert on this


subject, but because I'm not. I don't use C often, and
the combination of infrequent use and relatively obscure
syntax makes them frustrating to deal with. So I threw
these notes together to make sure that what I did know
was in an accessible form.
This document originally contained two chapters on C++,
but they were sketchy and I had little interest in the language. C++ is really not so much an enhancement of C as
it is a dierent language based on C. For the very small
software projects I tend to work on, its additional features
are much more bother than they're worth. Since I couldn't
maintain that material, I deleted it.
Revision history:
v1.0 / 01 jan 95 / gvg v2.0 / 01 may 95 / gvg / Added
chapters on C++, reformatted. v2.1 / 30 may 95 / gvg /
Minor corrections and changes. v2.2 / 01 jul 95 / gvg /
Added quick reference and minor changes. v2.3 / 09 jul
95 / gvg / Corrected bug in strlen()" description. v2.4 /
25 aug 95 / gvg / Added command-line parser example.
v2.5 / 13 oct 95 / gvg / Web update. v2.5 / 01 feb 99 / gvg
/ Minor cosmetic update. v2.0.7 / 01 feb 02 / gvg / Minor
cosmetic update. v3.0.0 / 01 aug 03 / gvg / Eliminated
C++ material. v3.0.1 / 01 aug 05 / gvg / Minor proong
& cleanup. v3.0.2 / 01 jul 07 / gvg / Minor cosmetic
update.

30

Chapter 7

Resources and Licensing


7.1 Resources

7.1.1

Wikimedia Resources

C Programming
C++ Programming/Code/Standard C Library

7.1.2

Other Resources

http://www.vectorsite.net
Learn C Language

7.2 Licensing

7.2.1

Licensing

The original text of this book was released into the public
domain by its author, Greg Goebel. The text of the book
is available at http://www.vectorsite.net/tscpp.html, and
that original version is still available in the public domain.
The version here at Wikibooks is released under the following license:

31

Chapter 8

Text and image sources, contributors, and


licenses
8.1 Text
Wikibooks:Collections Preface Source: https://en.wikibooks.org/wiki/Wikibooks%3ACollections_Preface?oldid=2842060 Contributors: RobinH, Whiteknight, Jomegat, Mike.lifeguard, Martin Kraus, Adrignola, Magesha and MadKaw
A Little C Primer/An Introductory C Program Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/An_Introductory_C_
Program?oldid=2683314 Contributors: Whiteknight, Sv1xv, Kd7nyq~enwikibooks, Makoryu, Fishpi, ReubenGarrett, Jfmantis, Zhaofeng
Li, AllenZh, GiovanniES and Anonymous: 7
A Little C Primer/C Functions in Detail Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_Functions_in_Detail?oldid=
2551325 Contributors: Whiteknight, Makoryu, Carlos RH Ruiz, Ebaychatter0, S Rifqi and Anonymous: 1
A Little C Primer/C Control Constructs Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_Control_Constructs?oldid=
2409797 Contributors: Whiteknight, Makoryu and Anonymous: 2
A Little C Primer/C Variables, Declarations and Constants Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_Variables%
2C_Declarations_and_Constants?oldid=2511735 Contributors: Whiteknight, Thenub314, Rbonvall, Fauxmight, 4crickj, RomanSaveljev
and Anonymous: 4
A Little C Primer/C Operators Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_Operators?oldid=2438195 Contributors:
Whiteknight, Fauxmight, HethrirBot and Fender0107401
A Little C Primer/C Preprocessor Directives Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_Preprocessor_Directives?
oldid=2616802 Contributors: Whiteknight, Fishpi, RayOctopus and Anonymous: 1
A Little C Primer/C Console IO Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_Console_IO?oldid=2239015 Contributors: Whiteknight, Fauxmight, Jfmantis and Anonymous: 1
A Little C Primer/C File-IO Through Library Functions Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_File-IO_
Through_Library_Functions?oldid=1548907 Contributors: Whiteknight and Fauxmight
A Little C Primer/C File-IO Through System Calls Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_File-IO_Through_
System_Calls?oldid=2840170 Contributors: Whiteknight, QuiteUnusual and Anonymous: 4
A Little C Primer/C Math Library Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_Math_Library?oldid=2239018 Contributors: Whiteknight and Jfmantis
A Little C Primer/C Standard Utility Library & Time Library Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_
Standard_Utility_Library_%26_Time_Library?oldid=2321402 Contributors: DavidCary, Whiteknight and Fauxmight
A Little C Primer/The C sprintf Function Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/The_C_sprintf_Function?oldid=
2410276 Contributors: DavidCary, Whiteknight, Sigma 7, Ebaychatter0 and Anonymous: 2
A Little C Primer/C String Function Library Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_String_Function_Library?
oldid=2459794 Contributors: DavidCary, Whiteknight, Denispir, Sigma 7, Mabdul, Fauxmight, Ebaychatter0 and Anonymous: 5
A Little C Primer/C Character Class Test Library Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_Character_Class_
Test_Library?oldid=1274974 Contributors: Whiteknight
A Little C Primer/C Command Line Arguments Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_Command_Line_
Arguments?oldid=1551853 Contributors: Whiteknight, Fauxmight and Anonymous: 2
A Little C Primer/Pointers to C Functions Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/Pointers_to_C_Functions?oldid=
2301673 Contributors: Whiteknight, , Jfmantis and Anonymous: 2
A Little C Primer/C Dynamic Memory Allocation & Deallocation Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_
Dynamic_Memory_Allocation_%26_Deallocation?oldid=2421314 Contributors: Whiteknight, Sergioller and Anonymous: 2
A Little C Primer/Common Programming Problems in C Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/Common_
Programming_Problems_in_C?oldid=2364113 Contributors: DavidCary, Whiteknight, Avicennasis, Reyk and Anonymous: 1

32

8.2. IMAGES

33

A Little C Primer/C Quick Reference Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/C_Quick_Reference?oldid=2457943


Contributors: Whiteknight and Anonymous: 1
A Little C Primer/Comments and Revision History Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/Comments_and_
Revision_History?oldid=1274980 Contributors: Whiteknight
A Little C Primer/Resources Source: https://en.wikibooks.org/wiki/A_Little_C_Primer/Resources?oldid=1933272 Contributors: DavidCary, Whiteknight and Anonymous: 1
A Little C Primer/Licensing Source:
Whiteknight and Avicennasis

https://en.wikibooks.org/wiki/A_Little_C_Primer/Licensing?oldid=2053016 Contributors:

8.2 Images
File:Heckert_GNU_white.svg Source: https://upload.wikimedia.org/wikipedia/commons/2/22/Heckert_GNU_white.svg License: CC
BY-SA 2.0 Contributors: gnu.org Original artist: Aurelio A. Heckert <[email protected]>
File:Wikibooks-logo-en-noslogan.svg Source: https://upload.wikimedia.org/wikipedia/commons/d/df/Wikibooks-logo-en-noslogan.
svg License: CC BY-SA 3.0 Contributors: Own work Original artist: User:Bastique, User:Ramac et al.

8.3 Content license


Creative Commons Attribution-Share Alike 3.0

You might also like