A Little C Primer
A Little C Primer
A Little C Primer
Contents
0.1
Wikibooks:Collections Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
0.1.1
What is Wikibooks? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
0.1.2
0.1.3
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
0.1.4
Wikibooks in Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
0.1.5
Happy Reading!
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.1
An Introductory C Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2
C Functions in Detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3
C Control Constructs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1
2.2
C Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
2.3
C Preprocessor Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
15
3.1
C Console IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
3.2
17
3.3
19
21
4.1
C Math Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
4.2
21
4.2.1
further reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
22
4.3.1
22
4.4
22
4.5
24
4.6
24
4.7
Pointers to C Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
4.8
25
4.9
26
4.3
ii
5
CONTENTS
C Quick Reference
28
5.1
28
30
6.1
30
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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
8.1
Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
8.2
Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
8.3
Content license . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
0.1.1
What is Wikibooks?
CONTENTS
0.1.5
Happy Reading!
Chapter 1
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.
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:
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:
oat result;
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:
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.
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 ) ...
This prints:
a=1 b=100
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:
while( 1 ) { ... }
}
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
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
10
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:
-- 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;
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
-- 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:
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
13
() [] -> . ! ~ ++ -- (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
_________________________
14
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
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:
%6.3f
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:
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; }
-- prints:
/* 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.
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
17
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.
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
remove( <le_name_string> )
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
19
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:
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
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
math library
#include <stdlib.h>
command-line arguments
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>
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 ); }
22
4.2.1
further reading
C Programming/Standard libraries
C Programming/C Reference
C++ Programming/Code/Standard C Library
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
23
A stricmp()" function that ignores case in comparisons.
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()
These two functions are only implemented in some compilers and are not part of ANSI C.
24
further reading
C Programming/Strings
C++ Programming/Code/IO/Streams/string
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:
25
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:
size_t
*<block_pointer>,
size_t
26
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:
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]
data[ 2, 7 ]
-- 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').
27
Chapter 5
C Quick Reference
5.1 C Quick Reference
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.
28
29
Chapter 6
30
Chapter 7
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
32
8.2. IMAGES
33
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.