0% found this document useful (0 votes)
254 views

ANSI C Programming Reference PDF

This document provides an overview of keywords and concepts in ANSI C programming. It includes 10 sections that cover data type keywords, flow control keywords, loop control keywords, the struct keyword, storage class keywords, program elements and structure, functions and passing arguments, operators and expressions, and bitwise operations. The table of contents lists over 40 sub-topics that are discussed within these main sections.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
254 views

ANSI C Programming Reference PDF

This document provides an overview of keywords and concepts in ANSI C programming. It includes 10 sections that cover data type keywords, flow control keywords, loop control keywords, the struct keyword, storage class keywords, program elements and structure, functions and passing arguments, operators and expressions, and bitwise operations. The table of contents lists over 40 sub-topics that are discussed within these main sections.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 44

ANSI C Programming Reference.

ANSI C Programming Reference Chapter 0:

1
ANSI C Programming Reference Chapter 0:

Table of Contents
1. C KEYWORD OVERVIEW ........................................................................................................................5

2. DATA TYPE KEYWORDS ........................................................................................................................6


2.1. Variable declaration 6
2.2. int - data type 6
2.3. float - data type 6
2.4. double - data type 6
2.5. char - data type 6
2.6. Modifiers - short, long, signed, unsigned 6
2.7. void - data type. 7
2.8. enum - data type 7
2.9. const - qualifier 8
2.10. volatile - qualifier. 8
2.11. Data type conversion 8
2.12. Cast, typecasting 8
2.13. The sizeof operator 9

3. FLOW CONTROL KEYWORDS...............................................................................................................9


3.1. The break keyword 9
3.2. The case, switch and default keywords 9
3.3. The continue keyword 10
3.4. The if and else keywords 11
3.5. The goto keyword. 12
3.6. The return keyword 12
3.7. Return with status: the exit function 13

4. LOOP CONTROL KEYWORDS .............................................................................................................13


4.1. Iteration vs Recursion 13
4.2. The do keyword 13
4.3. The for keyword. 14
4.4. The while keyword. 15

5. THE STRUCT KEYWORD ......................................................................................................................16


5.1. Structure basics 16
5.2. Structure membership 16
5.3. Pointers to structures 17

6. STORAGE CLASS KEYWORDS............................................................................................................18


6.1. auto - Storage Class 18
6.2. register - Storage Class 18
6.3. static - Storage Class 18
6.4. extern - Storage Class 19
6.5. The typedef keyword. 19
6.6. The union keyword. 20

2
ANSI C Programming Reference Chapter 0:

7. PROGRAM ELEMENTS AND STRUCTURE .........................................................................................20


7.1. Statements 20
7.2. Blocks 20
7.3. Comments. 21
7.4. C Compiler Preprocessors, # 21
7.5. Macros 22
7.6. Local variables 22
7.7. Global variables 22

8. FUNCTIONS AND PASSING ARGUMENTS..........................................................................................23


8.1. Function Basics. 23
8.2. Declaration. 23
8.3. Definition. 23
8.4. Passing values. 24
8.5. Passing pointers. 24
8.6. Passing Arrays. 24
8.7. Returning values. 25
8.8. Returning pointers. 25

9. OPERATORS AND EXPRESSIONS.......................................................................................................25


9.1. Arithmetic 25
9.2. Assignment 26
9.3. Logical/Relational 26
9.4. Bitwise 26
9.5. Odds and ends! 26
9.6. true or false. 26
9.7. Confusion of == and = in IF statements 27
9.8. Idioms 27
9.9. 27
9.9. Operator Precedence 27

10. BITWISE OPERATIONS .........................................................................................................................1


10.1. AND OR and XOR 1
10.2. One's Complement 30
10.3. Bit shift. 30

11. CONSTANTS ........................................................................................................................................30


11.1. Integer constants. 30
11.2. Floating point constants. 31
11.3. Chararacter constants. 31
11.4. String constants. 31

12. ARRAYS................................................................................................................................................31
12.1. int and float arrays 31
12.2. Two dimensional int and float arrays. 32
12.3. char arrays. 32
12.4. Two dimensional char arrays. 33

3
ANSI C Programming Reference Chapter 0:

13. POINTERS. ...........................................................................................................................................33


13.1. First Principles. 33
13.2. Pointer definition. 34
13.3. Pointers to arrays 35
13.4. Char Arrays versus Char pointers 35
13.5. Void Pointers 36
13.6. Pointers to functions 36
13.7. Linked Lists 36
13.8. The malloc function 37

14. STRINGS AND CHARACTERS ............................................................................................................37


14.1. Pointers to strings. 38
14.2. printf, sprintf, fprintf, scanf format identifiers. 38
14.3. Escape sequences. 39
14.4. Ascii character table in Hex. 40

15. FUNCTIONS SUMMARY ......................................................................................................................40


15.1. ANSI standard libraries. 40
15.2. ctype.h 40
15.3. math.h 41
15.4. stdio.h 41
15.5. stdlib.h 41
15.6. string.h 41
15.7. time.h 42

16. C PROGRAMMING EXAMPLES ..........................................................................................................42

17. GLOSSARY OF C TERMS. ..................................................................................................................43

4
ANSI C Programming Reference Chapter 1:

1. C Keyword Overview

The following list shows all the ANSI defined C keywords. I have included sizeof because it looks like a keyword.
Keyword Chapter Section Page
auto Storage Class Keyword 6.1 19
break Flow Control Keywords 3.1 10
case Flow Control Keywords 3.2 10
char Data Type Keywords 2.5 6
const Data Type Keywords 2.9 8
continue Flow Control Keywords 3.3 11
default Flow Control Keywords 3.2 10
do Loop Control Keywords 4.2 14
double Data Type Keywords 2.4 6
else Flow Control Keywords 3.4 11
enum Data Type Keywords 2.8 7
extern Storage Class Keyword 6.4 20
float Data Type Keywords 2.3 6
for Loop Control Keywords 4.3 14
goto Flow Control Keywords 3.5 12
if Flow Control Keywords 3.4 11
int Data Type Keywords 2.2 6
long Data Type Keywords - Modifiers 2.6 6
register Storage Class Keyword 6.2 19
return Flow Control Keywords 3.6 13
short Data Type Keywords - Modifiers 2.6 6
signed Data Type Keywords - Modifiers 2.6 6
sizeof Data Type Keywords 2.13 9
static Storage Class Keyword 6.3 19
struct The STRUCT Keyword 5 16
switch Flow Control Keywords 3.2 10
typedef Storage Class Keyword 6.5 20
union Storage Class Keyword 6.6 20
unsigned Data Type Keywords - Modifiers 2.6 6
void Data Type Keywords 2.7 7
volatile Data Type Keywords 2.10 8
while Loop Control Keywords 4.4 16

5
ANSI C Programming Reference Chapter 2:

2. Data Type Keywords


2.1. Variable declaration
C has a concept of 'data types' which are used to declare a variable before its use. The declaration assigns storage for
the variable and defines the type of data that will be held in the location.

int float double char void enum

Please note that there is not a boolean data type. C does not have the traditional view about logical comparison, but
thats another story.

2.2. int - data type


int is used to define integer numbers.
{
int Count;
Count = 5;
}

2.3. float - data type


float is used to define floating point numbers.
{
float Miles;
Miles = 5.6;
}

2.4. double - data type


double is used to define BIG floating point numbers. It reserves twice the storage for the number. On PCs this is
likely to be 8 bytes.
{
double Atoms;
Atoms = 2500000;
}

2.5. char - data type


char defines characters.
{
char Letter;
Letter = 'x';
}

2.6. Modifiers - short, long, signed, unsigned


The above data types have the following modifiers:
short long signed unsigned

The modifiers define the amount of storage allocated to the variable. The amount of storage allocated is not cast in
stone. ANSI has the following rules:

short int <= int < long int


float <= double <= long double

What this means is that a 'short int' should assign less than or the same amount of storage as an 'int' and the 'int'
should be less bytes than a 'long int'.What this means in the real world is:

6
ANSI C Programming Reference Chapter 2:

short int - 2 bytes (16 bits)


int int - 2 bytes (16 bits)
long int - 4 bytes (32 bits)
signed char - 1 byte (Range -128 ... +127)
unsigned char - 1 byte (Range 0 ... 255)
float - 4 bytes
double - 8 bytes
long double - 8 bytes
These figures only apply to todays generation of PCs. Mainframes and midrange machines could use different
figures, but would still comply with the rule above.
You can find out how much storage is allocated to a data type by using the sizeof operator.

2.7. void - data type.


The void keyword allows us to create functions that either do not require any parameters or do not return a value.
The following example shows a function that does not return a value.
void Print_Square(int Number)
{
printf("%d squared is %d\n",Number, Number*Number);
}
The next example shows a function that does not require any parameters:
int Random(void)
{
srand((unsigned int)time((time_t *)NULL));
return( rand());
}

2.8. enum - data type


enum is closely related to the #define preprocessor.
It allows you to define a list of aliases which represent integer numbers. For example if you find yourself coding
something like:
#define MON 1
#define TUE 2
#define WED 3
You could use enum as below.
enum week { Mon=1, Tue, Wed, Thu, Fri Sat, Sun} days;
or
enum boolean { FALSE = 0, TRUE };
An advantage of enum over #define is that it has scope This means that the variable (just like any other) is only
visible within the block it was declared within.

 Note:
• If a variable is defined with enum it is considered by the compiler to be an integer, and can have ANY integer
value assigned to it, it is not restericted to the values in the enum statement.

 See Also:
#define preprocessor.

 Example:
/* This program will compile but the #define statement
* will cause FALSE and TRUE to have a value of 1*/

enum Boolean_t {FALSE=0, TRUE} Boolean;

#define FALSE 1
main()
{
enum Boolean_t Boolean;

printf("False has a value of %d\n", FALSE);


printf(" True has a value of %d\n", TRUE);

7
ANSI C Programming Reference Chapter 2:
}
/*************** Resulting printout: ******************/
False has a value of 1
True has a value of 1

2.9. const - qualifier


The const qualifier is used to tell C that the variable value can not change after initialisation. For example:
const float pi=3.14159;
pi cannot be changed at a later time within the program.
Another way to define constants is with the #define preprocessor which has the advantage that it does not use any
storage (but who counts bytes these days?).

2.10. volatile - qualifier.


The volatile keyword acts as a data type qualifier. volatile means the storage is likely to change at anytime and be
changed but something outside the control of the user program. This means that if you reference the variable, the
program should always check the physical address (ie a mapped input fifo), and not use it in a cashed way.

 Examples
1) /* Base address of the data input latch */

volatile unsigned char *baseAddr;

/* read parts of output latch */

lsb = *handle->baseAddr;
middle = *handle->baseAddr;
msb = *handle->baseAddr;
Between reads the bytes are changed in the latch.Without the volatile, the compiler optimises this to a single
assignment:
lsb = middle = msb = *handle->baseAddr;
2)
A volatile variable is for dynamic use. E.G. for data that is to be passed to an I/O port Here is an example.
#define TTYPORT 0x17755U

volatile char *port17 = (char)*TTYPORT;


*port17 = 'o';
*port17 = 'N';
Without the volatile modifier, the compiler would think that the statement *port17 = 'o'; is redundant and
would remove it from the object code. The volatile statement prevents the compiler optimisation.

 See also:
Data type conversion - Storage classes. - cast - typedef keyword.

2.11. Data type conversion


An operator must have operands of the same type before it can carry out the operation. Because of this, C will
perform some automatic conversion of data types.
These are the general rules for binary operators (* + / % etc):

• If either operand is long double the other is converted to long double.


• Otherwise, if either operand is double the other is converted to double
• Otherwise, if either operand is float the other is converted to float
• Otherwise, convert char and short to int
• Then, if an operand is long convert the other to long.

2.12. Cast, typecasting


If you want to change the datatype of a variable you have to use a technic called cast. For example if want to change
an int to a float you could use the following syntax:

8
ANSI C Programming Reference Chapter 3:
main()
{
int var1;
float var2;

var2 = (float)var1;
}
As it happens this example would never be used in practice because C would perform the conversion automatically.
What this example does show is the cast operator () . This states, the result of the expression (in this case var1) is to
be a data type of float.

 See Also
typedef keyword.

2.13. The sizeof operator


sizeof will return the number of bytes reserved for a variable or data type.
The following code shows sizeof returning the length of a data type.

/* How big is an int? expect an answer of 4. */


main()
{
printf("%d \n", sizeof(int));
}
sizeof will also return the number of bytes reserved for a structure or an array.

/**** Purpose: Find out the size of the different data objects ****/

#include <stdio.h>

main()
{
char array[10];
struct s {
int a;
float b;
} structure;
.....
printf(" array is %i\n", sizeof array);
printf(" struct is %i\n", sizeof structure);
}
/**************** Resulting printout ************************
array is 10
struct is 8

 See also:
The strlen function Other operators malloc function.

3. Flow Control Keywords

3.1. The break keyword


This statement allows the program to escape from a for, while, do ... while, if block or switch structures. Ref
examples under case-switch for illustration of it's use.

3.2. The case, switch and default keywords


The switch-case statement is a multi-way decision statement. Unlike the multiple decision statement that can be
created using if-else, the switch statement evaluates the conditional expression and tests it against numerous constant

9
ANSI C Programming Reference Chapter 3:
values. The branch corresponding to the value that the expression matches is taken during execution.
The value of the expressions in a switch-case statement must be an ordinal type i.e. integer, char, short, long, etc.
Float and double are not allowed. The syntax is :
switch( expression )
{
case constant-expression1: statements1;
[case constant-expression2: statements2;]
[case constant-expression3: statements3;]
[default : statements4;]
}
The case statements and the default statement can occur in any order in the switch statement. The default clause is
an optional clause that is matched if none of the constants in the case statements can be matched. Consider the next
example:
switch( Grade )
{
case 'A' : printf( "Excellent" );
case 'B' : printf( "Good" );
case 'C' : printf( "OK" );
case 'D' : printf( "Mmmmm...." );
case 'F' : printf( "You must do better than this" );
default : printf( "What is your grade anyway?" );
}
Here, if the Grade is 'A' then the output will be:
Excellent
Good
OK
Mmmmm....
You must do better than this
What is your grade anyway?
This is because, in the 'C' switch statement, execution continues on into the next case clause if it is not explicitly
specified that the execution should exit the switch statement. The correct statement would be:
switch( Grade )
{
case 'A' : printf( "Excellent" );
break;

case 'B' : printf( "Good" );


break;

case 'C' : printf( "OK" );


break;

case 'D' : printf( "Mmmmm...." );


break;

case 'F' : printf( "You must do better than this" );


break;

default : printf( "What is your grade anyway?" );


break;
}
Although the break in the default clause (or in general, after the last clause) is not necessary, it is good
programming practice to put it in anyway.

3.3. The continue keyword


continue allows a new iteration of a loop without the current iteration completing. For example you could filter
records from a file with the continue statement. continue is related to the break statement. The following example
illustrates it's use:

/* To filter some records. Demonstrates 'continue', 'feof' & 'fgets' */


#include <stdio.h>

main()
{
char data[80]; /* Record read from the file. */
FILE *ptr; /* Pointer to the file. FILE is a
structure defined in <stdio.h> */

10
ANSI C Programming Reference Chapter 3:

/* Open the file - no error checking done */


ptr = fopen("/etc/hosts","r");
/* Read one record at a time, checking
for the End of File. EOF is defined
in <stdio.h> as -1 */
while (feof(ptr) == 0)
{
fgets(data, 80, ptr); /* Read next record */
if (data[0] == '#') continue; /* filter out the comments */
printf("%s",data); /* O/P the record to the screen */
}
fclose(ptr); /* Close the file. */
}

3.4. The if and else keywords


The if-else statement is a two-way decision statement. It is written as
if ( expression ) statement1;
[else statement2;]
The else portion is optional. If the expression evaluates to true (anything other than 0) then statement1 is executed. If
there is an else statement and the expression evaluates to false statement2 is executed. For example
(1)
int NumberOfUsers;
.....
if( NumberOfUsers == 25 )
{ /* No else part */
printf( "There are already enough users. Try later.\n" );
return ERROR;
}
.....
(2)
if( a >= b ) larger = a; /* else part is present */
else larger = b;
Consider this code fragment:
if( p == 1 )
if( q == 2 ) r = p * 2 + q;
else r = q * 2 + p;
Because the else part is optional, there is an ambiguity when an else is omitted from a nested if sequence. In 'C', this
is resolved by associating the else with the closest previous if that does not have an else. Therefore, in the above
example, the else part belongs to the if(q==2) statement. The code can be made more readable by explicitly putting
parentheses in the expression, like this:
if( p == 1 )
{
if( q == 2 ) r = p * 2 + q;
}
else r = q * 2 + p;
OR
if( p == 1 )
{
if( q == 2 ) r = p * 2 + q;
else r = q * 2 + p;
}
Because the statement in the else part can also be an if statement, a construct such as shown below is possible in 'C'
to create a multiple choice construct.

if( expression1 )
statement1;
else if( expression2 )
statement2;
else if( expression3 )
statement3;
.....
else
statementN;

11
ANSI C Programming Reference Chapter 3:

3.5. The goto keyword.


Well, I have resisted adding goto for a whole year. But tonight I have had a couple of beers and I am ready to go for
it. It must be said that most programmers will claim that goto is never required and I dont have reason to disagree,
but you may like to differ. The syntax is:

goto lab1;

lab1:
goto allows the program to 'jump' to a named label, in this case lab1, the target label MUST be terminated with a :
(colon).

 Example.
/* A division checking for divide by zero demonstrates the goto statement.*/
#include <stdlib.h>

main()
{
char data[100];
double num1, num2;

printf(" Please enter a number ==> " );


gets(data);
num1 = atof(data);

printf(" Please enter a number ==> " );


gets(data);
num2 = atof(data);
/* Stop a divide by zero with the goto statement. */
if ( num2 == 0.0 ) goto end_prog;

printf(" %4.2f divided by %4.2f is %4.2f\n", num1, num2, num1/num2);

end_prog:
printf(" Program ended\n");
}

3.6. The return keyword


return will return a value from a function to its caller. The value is the result of an expression.
As an Example, this will print 7:

int func(void);

main()
{
printf("%d \n", func());
}
int func(void)
{
return 7;
}
What ever follows the return statement will be evaluated as an expression. So, to be consistant you should place
brackets around the return value.
return(7);

Or you could evaluate a formula on the statement:


return (Count-1);

Finally, if the function returns a void the return statement is not required, but maybe needed to leave a function
before the end of the function block. Here is an example.
void CheckDate(int)

main()

12
ANSI C Programming Reference Chapter 4:
{
CheckDate(40)
}

void CheckDate(int Month)


{
if (Month > 31)
{
return;
}
puts("Month is valid");
}

3.7. Return with status: the exit function


exit causes the program to end and supplies a status code to the calling environment.
Library: stdlib.h
Prototype: void exit(int status);
Syntax:
main()
{
exit(0); /* Clean exit */
}

4. Loop Control Keywords


4.1. Iteration vs Recursion
Most problems that can be solved with iteration ( for, while, do loops) can also be solved with recursion. Pros and
cons are:

• Iteration code will be faster and will use less resources.


• Recursion normaly looks more like the original formula.
Anyway up, as an example of both technics here is some code to give the factorial of a number:
#include <stdio.h>
int factorial(int num);

main()
{
int num;
puts ("This program will return the factorial of a number.");
printf("Please enter the number ==> " );
scanf("%d", &num);
printf(" %d! is %d\n",num, factorial(num) );
}

int factorial(int num) /* Iteration */ int factorial(int num) /*Recursion*/


{ {
int count, ans=1; int ans=1;
for (count=1; count <= num; count++ ) ans *= count; if (num == 1 ) return;
return ans; ans = num * factorial(num-1);
} return ans;
}

4.2. The do keyword


The do keyword performs a simular function to while. Basicaly, it repeats a block of statements. Here is an example
of the syntax:
main()
{
int i=5;

13
ANSI C Programming Reference Chapter 4:
do
{
printf(" i is %d\n", i);
}
while(--i);
}
The program result will look like this:
i is 5
i is 4
i is 3
i is 2
i is 1
The main difference between do and while is the time that expression is evaluated.

• do performs the first test AFTER the first iteration. 'do...while' works like 'repeat ...until' in Pascal.
• while performs the first test BEFORE the first iteration.

4.3. The for keyword.


The for keyword is used to repeat a block of code many times.

 Basic principles
Say you wanted to print all the numbers between 1 and 5, you could write:
main()
{
int count=1;
printf("%d\n", count++);
printf("%d\n", count++);
printf("%d\n", count++);
printf("%d\n", count++);
printf("%d\n", count++);
}
As you can see this program would NOT be very practical if we wanted 500 numbers. The problem can be solved
with the for statement as below.
main()
{
int count;

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


}
The for statement can be broken down into 4 sections:
count=1 is the initalisation.
count <= 5 is an expression. The for statement continues to loop while this statement remains true
count++ means increment for each round of the loop (-- means decrement).
printf("%d\n", count) is the statement to execute.

 Repeating several lines of code


The previous example showed how to repeat ONE statement. This example shows how many lines can be repeated.
#include <stdio.h>
int main()
{
int count, sqr;
for ( count=1 ; count <= 10 ; count++);
{
sqr=count * count;
printf( " The square of");
printf( " %2d", count);
printf( " is %3d\n", sqr);
}
}
The {.....} following the for statement define a block of statements.

 More detail
The for statement performs the following actions while looping.

14
ANSI C Programming Reference Chapter 4:
for (expression_1 ; expression_2 ; expression_3) statement ;
1. Execute expression_1.
2. Evaluate expression_2, AND, if TRUE proceed; if FALSE exit the loop.
3. Execute statement.
4. Execute expression_3.
5. Repeat step 2.

Any of the three expressions can be missing; if the first or third is missing, it is ignored.
If expression_2 is missing, it is assumed to be TRUE.
Note, however, that both semicolons (;) are required. Also, be aware that statement may NEVER be executed
as it is possible expression_2 will be FALSE the first time it is evaluated.

Another way to think of a basic for loop is as:

expression_1;
while (expression_2)
{
statement(s);
expression_3;
}
The following example is an infinite loop:
main()
{
for( ; ; ) puts(" Linux rules!");
}

4.4. The while keyword.


The while keyword is related to do and for. Its purpose is to repeatedly execute a block of statements, for example :
main()
{
int i=5;

while(--i)
{
printf(" i is %d\n", i);
}
}
The expression i-- is evaluated and if its true the statements in the block are executed. The loop continues until the
expression is false (zero). The result will look like this:
i is 4
i is 3
i is 2
i is 1
It is important to note that the statements on a while will not get executed if the first evaluation of the expression is
FALSE. If you do not want this to happen you may prefer to use the do statement. Now consider the next example:

main()
{
int i=5;

while(--i);
{
printf(" i is %d\n", i);
}
}
The result will look like this:
i is 0

This is because of the ; at the end of the while statement which means the while will loop (executing NULL
statements) until i is zero. Execution will then continue down the program (to the printf).

15
ANSI C Programming Reference Chapter 5:

 See also:
break keyword - continue keyword.

5. The struct keyword


5.1. Structure basics
struct is used to declare a new data-type. Basically this means grouping variables together. For example, a struct
data type could be used to declare the format of the following file.

Jo Loss Maths A
Harry Carpenter English A
Billy King Maths C

The records above could be described in a struct as follows:

struct {
char cname[8];
char sname[16];
char exam[16];
char grade;
} record;

The statement above declare a variable called record with 4 members called cname, sname, exam, grade. The
structure as a whole can be referred to as record and a member can be referenced as record.exam. Structures can be
declared in various forms...
struct x {int a; int b; int c;}; /* declaration */
struct {int a; int b; int c;} z;
struct x z;
All the examples above are structure declarations,
• The first gives x as a 'structure tag' - this is optional.
• The first and second declare the members of the structure.
• Second and third give z this is the variable that assumes thestructure type.

5.2. Structure membership


We can access individual members of a structure with the . operator. For example to assign a value, we can enter:
struct x {int a; int b; int c;};

main()
{
struct x z;

z.a = 10;
z.b = 20;
z.c = 30;
}
And to retrieve a value from a structure member:
struct x {int a; int b; int c;} ;

main()
{
struct x z;

z.a = 10;
z.a++;
printf(" first member is %d \n", z.a);
}

16
ANSI C Programming Reference Chapter 5:

5.3. Pointers to structures


All that we have discussed so far has been OK but runs into problems when structures have to be moved between
functions for the following reasons:

• If the structure is large it is more efficient to pass a pointer to the structure instead of the structure its self. This
technic is also used to pass pointers to arrays between functions.
• When passing a structure to a function, you actually pass a COPY of the structure. Therefore it is not possible to
change the values of members within the structure as the copy is destroyed when the function ends.
So how does it all work? Here is an example.
struct x {int a; int b; int c;} ; | struct x {int a; int b; int c;} ;
void function(struct x); | void function(struct x *);
|
main() | main()
{ | {
struct x z; | struct x z, *pz; /* 3 */
| pz = &z; /* 4 */
z.a = 10; /* 1 */ | z.a = 10;
z.a++; | z.a++;
|
function(z); /* 2 */ | function(pz); /* 5 */
} | }
void function( struct x z) | void function(struct x * pz)
{ | { /* 6 */
printf(" first member %d \n", z.a); | printf(" first member %d \n", (*pz).a);
} | }
Here is the annotation.
1. Give a structure member a value.
2. Pass a COPY of the whole structure to the function.
3. Define 'pz' a pointer to a structure of type 'x'.
4. Put the address of 'z' into 'pz'. 'pz' now POINTS to 'z'. PLEASE NOTE. 'z' is defined to reserve memory equal to
the size of the structure. 'pz' only holds an address so will be 4 bytes long.
5. Pass the pointer into the function.
6. Print the value of the member 'a'.

The (*pz).a syntax is used a great deal in C and it was decided to create ashort hand for it. So:
(*pz).a == pz->a

Here is the final picture:

struct x {int a; int b; int c;} ; /* Declare the structure.*/


void function(struct x * ); /* Declare the function. */

main()
{
/* Declare two variables: *z == type struct x
and * pz == a pointer to type struct x */
struct x z, *pz;

pz = &z; /* put the address of 'z' into 'pz' */


z.a = 10; /* initialize z.a */
z.a++; /* Increment z.a */

/* print the contents of 'z.a' using the pointer 'pz'*/


printf(" first member before the function call %d \n", pz->a);

/* Call 'function' passing the pointer 'pz' */


function(pz);

/* Print NEW value of 'z.a' using three different notations */


printf(" first member after the function call %d \n", pz->a);
printf(" first member after the function call %d \n", (*pz).a);
printf(" first member after the function call %d \n", z.a);
}

17
ANSI C Programming Reference Chapter 6:
void function(struct x * pz)
{
/* Print the value of 'z.a' by referencing the pointer 'pz'
which holds the address of 'z' */
printf(" first member inside the function %d \n", pz->a);

/* Increment the value of 'z.a' at the source location in memory. */


pz->a++;
}

 See Also:
typedef keyword. - Linked lists.

6. Storage Class Keywords


C has a concept of 'Storage classes' which are used to define the scope (visibility) and life time of variables and/or
functions. So what Storage Classes are available?
auto register static extern typedef

6.1. auto - Storage Class


auto is the default storage class for local variables.
{
int Count;
auto int Month;
}
The example above defines two variables with the same storage class. auto can only be used within functions, i.e.
local variables.

6.2. register - Storage Class


register is used to define local variables that should be stored in a register instead of RAM. This means that the
variable has a maximum size equal to the register size (usually one word) and cant have the unary '&' operator
applied to it (as it does not have a memory location).
{
register int Miles;
}
Register should only be used for variables that require quick access - such as counters. It should also be noted that
defining 'register' does not mean that the variable will be stored in a register. It means that it might be stored in a
register - depending on hardware and implementation restrictions.

6.3. static - Storage Class


static is the default storage class for global variables. The two variables below (count and road) both have a static
storage class.
static int Count;
int Road;

{
printf("%d\n", Road);
}
static variables can be 'seen' within all functions in this source file. At link time, the static variables defined here will
not be seen by the object modules that are brought in.
'static' can also be defined within a function! If this is done the variable is initalised at run time but is not reinitalized
when the function is called. This is serious stuff - tread with care.
{
static Count=1;
}
There is one very important use for 'static'. Consider this bit of code.
char * func(void);

18
ANSI C Programming Reference Chapter 6:

main()
{
char *Text1;
Text1 = func();
}

char * func(void)
{
char Text2[10]="martin";
return(Text2);
}
Now, 'func' returns a pointer to the memory location where 'text2' starts BUT text2 has a storage class of 'auto' and
will disappear when we exit the function and could be overwritten by something else. The answer is to specify
static char Text[10]="martin";
The storage assigned to 'text2' will thus remain reserved for the duration if the program.

6.4. extern - Storage Class


extern defines a global variable that is visible to ALL object modules (e.g. Source 1 and Source 2 below). When you
use 'extern' the variable cannot be initalized as all it does is point the variable name at a storage location that has
been previously defined.

Source 1 | Source 2
-------- | --------
extern int count; | int count=5;
|
write() | main()
{ | {
printf("count is %d\n", count); | write();
} | }
Count in 'source 1' will have a value of 5. If source 1 changes the value of count - source 2 will see the new value.

6.5. The typedef keyword.


Every variable has a data type. typedef is used to define new data type names to make a program more readable to
the programmer. For example:
|
main() | main()
{ | {
int money; | typedef int Pounds;
money = 2; | Pounds money = 2
} | }
These examples are EXACTLY the same to the compiler. But the right hand example tells the programmer the type
of money he is dealing with. A common use for typedef is to define a boolean data type:
typedef enum {False=0, TRUE} Boolean

main ()
{
Boolean flag = TRUE;
}
And as a final example, how about creating a string datatype?
typedef char * String;

main()
{
String Text = "Thunderbird";

printf("%s\n", Text);
}

The main use for typedef seems to be when defining structures. For example:
typedef struct {int age; char *name} person;
person people;

Take care to note that person is now a type specifier and NOT a variable name.
I would expect to see 'typedef' in header files.

19
ANSI C Programming Reference Chapter 7:

6.6. The union keyword.


The union keyword allows several variables of different type and size to occupy the same storage location.The
syntax to define a union is simular to the struct keyword as shown below:
union union_def { int a; float b; char c;} ;

and a variable declared with either of these statements:


union union_def union_var;
union { int a; float b; char c;} union_var;

If you wish to initalise a variable you can say:


union { int a; float b; char c;} union_var=97;

By default the first variable (a) is initalised. To assign a value to a variable you can say:
union_var.b=99.99;
union_var.a=34;
union_var.c='x';

It's important to note that the storage will only hold ONE value, looking at the three lines above, union_var.a
overwrites union_var.b and then union_var.c overwrites union_var.a
I have yet to see more than one use for this keyword.

 See Also:
Data types.

7. Program Elements and Structure


7.1. Statements
C has three types of statement.

• assignment
=
• selection (branching)
if (expression)
else
switch
• iteration (looping)
while (expression)
(expression;expression;expression)
do {block}

7.2. Blocks
These statements are grouped into blocks, a block is identified by curly brackets.There are two types of block.

• statement blocks
if ( i == j)
{
printf("martin \n");
}
• The statement block containing the printf is only executed if the i == j expression evaluates to TRUE.
• function blocks
int add( int a, int b) /* Function definition */
{
int c;
c = a + b;
return c;
}
• The statements in this block will only be executed if the add function is called.

20
ANSI C Programming Reference Chapter 7:

7.3. Comments.
Lets start with a few examples.
main()
{
int Counter=0; /* Initalise Counter */

/* a comment */

/*
* Another comment
*/

/*****************
*
* Final comment.
*
*****************/
}
A comment starts with a /* and ends with */. Comments started in this way can span multiple lines but cannot be
nested !! For example:

main()
{
int Count = 0; /* Initalise
* Counter to 0 */
/* /* Invalid comment */ */
}
This will give a syntax error, since comments within comments are illegal.

 Warning!: C++ notation


C++ allows // as an inline comment, it can be used on any line and is delimited by the newline character (return).
Many C-compilers, however, do not allow this.
main()
{
int Counter = 0; // Initalise Counter.

/* Start the main processing here. */


}

7.4. C Compiler Preprocessors, #


Preprocessor commands are executed before the compiler compiles the source code. These commands will change
the original code usually to suit the operating environment and/or to add code that will be required by calls to library
functions. Preprocessors are recognised by the leading # in their names, as listed below:

#include Insert a source file.


#define Define a preprocessor constant.
#if Branch based on an expression.
#ifdef Branch if preprocessor constant has been defined?
#ifndef Branch is a preprocessor constant has NOT been defined.
#line Specify the number of the next source line.
#undef Remove a preprocessor constant.
#pragma Perform an implementation dependent action???
#else Executed if #if #ifdef or #ifndef fails.
#error Write an error message.
#elif Executed when an #if fails.
#endif Close #if #ifdef or #ifndef

 Note:
• Preprocessors should start in column 1.

21
ANSI C Programming Reference Chapter 7:

7.5. Macros
Macros are built on the #define preprocessor.
Normally a #define would look like:
#define PI 3.142

But, a macro would look like this.


#define SQUARE(x) x*x

The main difference is that the first example is a constant and the second is an expression. If the macro above was
used in some code it may look like this:
#define SQUARE(x) x*x

main()
{
int value=3;
printf("%d \n", SQUARE(value));
}
After preprocessing the code would become:
main()
{
int value=3;
printf("%d \n", value*value);
}

 Notes:
• The value passed to SQUARE could have been an int float or double
• Long macros can span multiple lines by using a followed by a newline (return).

7.6. Local variables


Local variables must always be defined at the top of a block. When a local variable is defined - it is not initalised by
the system, you must initalise it yourself. A local variable is defined inside a block and is only visable from within
the block.
main()
{
int i=4;
i++;
}
When execution of the block starts the variable is available, and when the block ends the variable 'dies'. A local
variable is visible within nested blocks unless a variable with the same name is defined within the nested block.
main()
{
int i=4;
int j=10;
i++;
if (j > 0)
{
printf("i is %d\n",i); /* i defined in 'main' can be seen */
}
if (j > 0)
{
int i=100; /* 'i' defined in and local to this block */
printf("i is %d\n",i);
} /* 'i' (value 100) dies here */
printf("i is %d\n",i); /* 'i' (value 5) is now visible. */
}

7.7. Global variables


Global variables ARE initalised by the system when you define them!
int == 0
char == \0
float == 0
pointer == NULL

22
ANSI C Programming Reference Chapter 8:

In this example i is a global variable, it can be seen and modified by main and any other functions that may
reference it.
int i=4;
main()
{
i++;
}

Now, this example has global and Internal variables.


int i=4; /* Global definition */
main()
{
i++; /* global variable */
func
}

func()
{
int i=10; /* Internal declaration */
i++; /* Internal variable */
}
i in main is global and will be incremented to 5. i in func is internal and will be incremented to 11. When control
returns to main the internal variable will die and and any reference to i will be to the global.

 See Also:
See Storage classes to see the more powerful features of variable declarations.

8. Functions and Passing Arguments.


A function is a block of code that can be executed many times by other functions, or itself.
• Function basics.
• Declaration.
• Definition.
• Passing values.
• Passing pointers.
• Passing Arrays.
• Returning values.
• Returning pointers.

8.1. Function Basics.


You should already understand the concept of functions! If you don't, you are a sad sad man....
P.S. main() is a function.

8.2. Declaration.
Just like variables, all functions have to be declared before use. Here is an example.
int add( int, int);
This statement declares a function called add, it has two integer arguments and returns an integer.

8.3. Definition.
The definition is the meat of the function. Here's an example.

int add( int, int); /* Function declaration */

main()
{

23
ANSI C Programming Reference Chapter 8:
int i=1;
printf("i starts out life as %d.", i);
i = add(1, 1); /* Function call */

printf(" And becomes %d after function is executed.\n", i);


}

int add( int a, int b) /* Function definition */


{
int c;
c = a + b;
return c;
}

8.4. Passing values.


Passing values is known as call by value. You actually pass a copy of the variable to the function. If the function
modifies the copy, the original remains unaltered. The previous example demonstarted call by value

8.5. Passing pointers.


This is known as call by reference and is an area worth spending some time on. We do not pass the data to the
function, instead we pass a pointer to the data. This means that if the function alters the data, the original is altered.

void add(int*); /* Function declaration */

main()
{
int i=4; /* variable declaration */
int* ptr; /* int pointer */
ptr = &i; /* 'ptr' now contains the address of 'i'*/

printf("i starts out life as %d.\n", i);


printf(" *ptr is %d.\n", *ptr);
add(ptr); /* Function call */
printf(" i is now %d.\n", i);
}
void add(int *ptr) /* Function definition */
{
++*ptr; /* Add 1 to the value pointed too by 'ptr' */
return;
}

8.6. Passing Arrays.


/* (1) Demonstrate passing a pointer to an array to a function.*/
#define I_SIZE 2

void add(int*); /* Function declaration */

main()
{
int i[I_SIZE]={4,6}; /* array declaration */
int count=0;
for (count=0;count<I_SIZE;count++)
printf("i starts out life as %d.\n", i[count]);

add(i); /* Function call */


for (count=0;count<I_SIZE;count++) \
printf(" i is now %d.\n", i[count]);
}

void add(int *ptr) /* Function definition */


{

24
ANSI C Programming Reference Chapter 9:
++*ptr; /* Add 1 to the first element in the array */
++*(ptr+1); /* And the second element */
return;
}

/* (2) Demonstrate passing a pointer to a character string to a function. */

int function1(char * array);

main()
{
char array1[10]="987654321"; /* one less so the \0 will fit */

function1(array1); /* call function */

printf("%s\n", array1); /* O/P the altered array. '5' will


* have been changed to 'x' */
}

function1(char * array)
{
printf("%s\n", array); /* printf expects a pointer. */

array +=4; /* Modify the pointer. */


*array = 'x'; /* Modify the data pointed to
* by 'array' */
}

8.7. Returning values.


Normally you would return an 'int', 'char', 'float', or 'double' using this technic. The obvious time to return a value
would be to return a completion code.
See example in section Definition above, where the contents of 'c' are copied into 'i'.

8.8. Returning pointers.


Returning values is OK for the data types above but not very practical for 'char *' or structures. For these data types
passing pointers can be more appropriate. When using these pointers it is importand to understand the 'static' storage
class otherwise you are going to get some unpredictable results.

9. Operators and Expressions


Operators are used with operands to build expressions. For example the following is an expression containing two
operands and one oprator.
4 + 5
The following list of operators is probably not complete but does highlight the common operators and a few of the
outrageous ones.C contains the following operator groups:

Arithmetic Assignment Logical/relational Bitwise Odds and ends!

9.1. Arithmetic
+
-
/
*
% modulo
-- Decrement (post and pre)
++ Increment (post and pre)

25
ANSI C Programming Reference Chapter 9:

9.2. Assignment
These all perform an arithmetic operation on the lvalue and assign the result to the lvalue. So what does this mean in
English? Here is an example:
counter = counter + 1;
can be reduced to
counter += 1;
Here is the full set.
=
*= Multiply
/= Divide.
%= Modulus.
+= add.
-= Subtract.
<<= left shift.
>>= Right shift.
&= Bitwise AND.
^= bitwise exclusive OR (XOR).
|= bitwise inclusive OR.

9.3. Logical/Relational
== Equal to
!= Not equal to
>
<
>=
<=
&& Logical AND
|| Logical OR
! Logical NOT

9.4. Bitwise
& AND (Binary operator)
| inclusive OR
^ exclusive OR
<< shift left
>> shift right
~ one's complement

9.5. Odds and ends!


sizeof() size of objects and data types.
strlen may also be of interest.
& Address of (Unary operator)
* pointer (Unary operator)
? Conditional expressions
: Conditional expressions
, Series operator.

9.6. true or false.


The concept of an expression evaluating to true or false is one of the corner stones of C. BUT the language derives
true and false in an unusual way. Basicly there is no boolean value. The number 0 is considered to be false and all
other numbers are considered to be true. Please consider the following expressions.
(1 == 1) true
(1 != 1) false
(i = 1) true
(i = 0) false
(i = 1 + 1) true
The first two examples should be clear but the last ones need explanation .
The last three examples assign a value to a variable and a side effect of assignment is to return the value assigned,
it is this value that is tested to be true or false. Looking at the last example:
(i = 1 + 1)
(i = 2)
(2)

26
ANSI C Programming Reference Chapter 9:
• The third expression assigns a value of 1 to i. 1 is considered to be true because it is non-zero.
• The fourth expression assigns a value of 0 to i. 0 is considered to be false.
• The fith expression assigns a value of 2 to i. 2 is considered to be true, because it is non-zero.

9.7. Confusion of == and = in IF statements


An error which almost every C programmer has made is shown below:
main()
{
int left=10;
if ( left = 5 )
{
puts(" Values are equal...");
}
}
The program assigns 5 to the variable left and returns 5. This is interpreted as TRUE and causes the puts statement
to be executed everytime. Here is the corrected program.
main()
{
int left=10;
if ( left == 5 )/* Two equals is required. */
{
puts(" Values are equal...");
}
}

9.8. Idioms
Here are some C idioms that may be useful.
• Place \0 at the location pointed to by ptr then increment ptr
*ptr++ = '\0';
• Increment ptr then place \0 at the location pointed to by ptr
*++ptr = '\0';
• This program will print itself! I guess it's not of any real use, but I think its clever.
main(a) {a="main(a) {a=%c%s%c;printf(a,34,a,34);}"; printf(a,34,a,34);}
^
|
9.9. Operator Precedence
&&
The following tables show the order in which operators
||
are evaluated. Please note the following.
?:
• The order in which the operands are evaluated is not
specified in the ANSII standard. = += -= *= /= %= &= ^= |= <<= >>=
• For readability you should not rely on these rules! ,
Put everything in brackets so you intension is clear
to the compiler and other programmers.

 Summary precedence
table.
All operators on the same line have the same
precedence. The first line has the highest precedence.

() [] -> .
! ~ ++ -- + - * & sizeof
* / %
+ -
<< >>
< <= >= >
== !=
&

27
ANSI C Programming Reference Chapter 10:
<= Less than or equal to.
 Detailed precedence >= Greater than or equal to.
table == Equal to.
All operators in the same block have the same prece- != Not equal to.
dence. The first block has the highest precedence. More Bitwise & bitwise AND
Group Operator Description ^ bitwise Excusive OR
Membership. () Function call. | bitwise OR
[] Array. Logical. && Logical AND
-> Structure pointer.
Logical. || Logical OR
. Structure member.
Conditional ?: Conditional construct.
Unary. ! Logical NOT
Assignment = Equals
~
+= assignment
++ Increment.
-= assignment
-- Decrement.
*= assignment
+
/= assignment
-
%= assignment
* Pointer to data
&= assignment
& Address of a variable.
^= assignment
sizeof
(type) type cast. |= assignment
<<= assignment
Binary * Multiply.
>>= assignment
/ Divide.
% Modulo. Series , Comma

Binary + Addition
- Subtraction.
Bitwise << Shift left.
>> Shift Right.
Relational < Less than.
> Greater than.

10. Bitwise operations


Bitwise operators include:
& AND | OR ^ XOR << Shift Left >> Shift Right ~ one,s complement
&= AND |= OR ^= XOR <<= Shift Left >>= Shift Right

10.1. AND OR and XOR


These require two operands and will perform bit comparisions.

AND & will copy a bit to the result if it exists in both operands.
main()
{
unsigned int a = 60; /* 60 = 0011 1100 */
unsigned int b = 13; /* 13 = 0000 1101 */
unsigned int c = 0;

c = a & b; /* 12 = 0000 1100 */


}

OR | will copy a bit if it exists in eather operand.


main()

1
ANSI C Programming Reference Chapter 11:
{
unsigned int a = 60; /* 60 = 0011 1100 */
unsigned int b = 13; /* 13 = 0000 1101 */
unsigned int c = 0;

c = a | b; /* 61 = 0011 1101 */
}

XOR ^ copies the bit if it is set in one operand (but not both).
main()
{
unsigned int a = 60; /* 60 = 0011 1100 */
unsigned int b = 13; /* 13 = 0000 1101 */
unsigned int c = 0;

c = a ^ b; /* 49 = 0011 0001 */
}

10.2. One's Complement


This operator is unary (requires one operand) and has the efect of 'flipping' bits.

main()
{
unsigned int Value=4; /* 4 = 0000 0100 */

Value = ~ Value; /* 251 = 1111 1011 */


}

10.3. Bit shift.


The following operators can be used for shifting bits left or right.
<< >> <<= >>=
The left operands value is moved (left or right) by the number of bits specified by the right operand. For example:
main()
{
unsigned int Value=4; /* 4 = 0000 0100 */
unsigned int Shift=2;

Value = Value << Shift; /* 16 = 0001 0000 */


Value <<= Shift; /* 64 = 0100 0000 */
Printf("%d\n", Value); /* Prints 64 */

Usually, the resulting 'empty' bit is assigned ZERO.Please use unsigned variables with these operators to avoid
unpredictable results.

11. Constants
Be sure you understand the difference between a 'constant' and a declaration. A constant has a value that cannot be
changed. For example:
1234
'x'
9.89
"String"
Constants are used to assign a value to a variable, e.g.
int i; /* declare a variable called 'i' */
i=1234; /* assign the constant value 1234 to
* the variable 'i' */
i++; /* Change the value of the variable. */

11.1. Integer constants.


Interger constants can be expressed in the following ways.
1234 (decimal)

30
ANSI C Programming Reference Chapter 12:
0xff (Hexidecimal)
0100 (Octal)
'\xf' (Hex character)
Examples of their use are:
int i=255; /* i assigned the decimal value of 255 */
i-=0xff /* subtract 255 from i*/
i+=010 /* Add Octal 10 (decimal 8) */

printf ("%i \n", '\xf'); /* Print 15 */


Integer constants are assumed to have a datatype of int, if it will not fit into an 'int' the compiler will assume the
constant is a long. You may also force the compiler to use 'long' by putting an 'L' on the end of the integer constant.
1234L /* Long int constant (4 bytes) */
The other modifier is 'U' for Unsigned.
1234U /* Unsigned int */
and to complete the picture you can specify 'UL'
1234UL /* Unsigned long int */

11.2. Floating point constants.


Floating point constants contain a decimal point or exponent. By default they are double.
123.4
1e-2

11.3. Chararacter constants.


Are actually integers.
'x'
'\000'
'\xhh'
See also ASCII Characters and Escape sequences

11.4. String constants.


Strings do not have a datatype of their own. They are actually a sequence of char items terminated with a \0. A string
can be accessed with a char pointer. An example of a string would be:
char *Str = "String Constant";
See the discussion on strings for more information.

 See also:
#define - Strings

12. Arrays.
Arrays can be created from any of the C data types int, float, char. I start with int and float as these are the easiest to
understand. Then move onto int and float multi dimentional arrays and finally char arrays

• int or float arrays.


• two dimensional int or float arrays.
• char arrays.
• char multidimentional arrays.

12.1. int and float arrays


To define an integer or floating point variable you would say.
main()
{
int count; /* interger variable */
float miles; /* floating point variable */
}

31
ANSI C Programming Reference Chapter 12:
The syntax for an array is:
main()
{
int count[5]; /* interger 5 element array */
float miles[10]; /* floating point 10 element array */
}
Now, the important fact is that the elements start at 0 (ZERO), so, 'count' above has elements 0, 1, 2, 3, 4.
To change the value of the 5th element we would code:
main()
{
int count[5];
count[4] = 20; /* index 4 is the 5th element */
}
If we want to initalise 'count' at definition we can say:
main()
{
int i;
int count[5]={10, 20, 30};
for (i=0; i< 5; i++)
{
printf("%d ", count[i]);
}
puts("")
}
The result will be:
10 20 30 0 0
We can see from the example above that the elements that have NOT been initalised have been set to zero.
One last thing to show you. If all the elements are being initialized when the variable is being declared, the compiler
can work out the number of elements for you. So this example will create an array with 3 elements.
main()
{
int i;
int count[]={10, 20, 30};
}
Don't forget all the stuff so far also applies to float.

12.2. Two dimensional int and float arrays.


C does not actually support multi-dimensional arrays, but you can emulate them.
main()
{
int count[5];
int matrix[10][4];
}
count has been seen before, it defines an array of 5 elements. matrix is defined as 10 arrays, all with 4 elements.
To initalise matrix at definition, you would code the following.
main()
{
int thingy[4][2]={{1, 2},
{3, 4},
{5, 6},
{7, 8}};
}
Dont forget the last element will be thingy[3][1]

12.3. char arrays.


char arrays work in the same way as int and float
main()
{
char letter;
char letters[10];
}
'letter' can only hold one character but 'the 'letters' array could hold 10. It is important to think of 'char' as an array
and NOT a string. To initalise 'char' variables you can use the following syntax.

32
ANSI C Programming Reference Chapter 13:
main()
{
char letter='x';
char letters[10]='f','a','x',' ','m','o','d','e','m','\0';
char text[10]="fax modem";
}
Note that the double quotes mean 'text string', so they will add the NULL automatically. This is the only time that
text can be loaded into an array in this way. If you want to change the contents of the array you should use the
function strcpy.

12.4. Two dimensional char arrays.


Two dimensional char arrays are a different kettle of fish! We can follow the rules above to define the array as below
but it does not appear to be of much use!
main()
{
char colours[][6]={"red","green","blue"};
}
Note we have specified 6 characters as a NULL will be added to the end of each string. The code above works, but
you dont seem to be able to access any of the strings! characters can be extracted as below:
main()
{
char colours[][6]={"red","green","blue"};
printf ("%c \n", colours[0][0]);
}
We don't have any pointers to the strings. To see how to get around this problem, read further about pointers.

13. Pointers.
Pointers are at the heart of C. When you crack this subject, you have got the worst of C behind you. Before you
tackle pointers though, you should get a grip on arrays.

• First principles.
• Definition of a pointer.
• Pointers to strings.
• Pointers to arrays.
• Char arrays verses char pointers.
• Void pointers.
• Pointers to pointers.
• Pointers to functions.
• Linked lists.

13.1. First Principles.


To understand pointers, it may be worth understanding how normal variables are stored. What does the following
program realy mean?
main()
{
int Length;
}
In my mind, it means, reserve enough storage to hold an integer and assign the variable name 'Length' to it. The data
held in this storage is undefined. Graphically it looks like:
(Address) (Data)
F1 <- ------ Length
F2
F3
F4

To put a known value into 'Length' we code,

33
ANSI C Programming Reference Chapter 13:
main()
{
int Length;
Length = 20;
}
the decimal value 20 (Hex 14) is placed into the storage location.
(Address) (Data)
F1 <- ------ Length
F2
F3
F4 14
Finally, the program is expanded to become:
main()
{
int Length;
Length = 20;
printf("Length is %d\n", Length);
printf("Address of Length is %p\n", &Length);
}
The output would look something like this .....
Length is 20
Address of Length is 0xF1

Please note the '&Length' on the second printf statement. The & means address of Length. If you are happy with
this, you should push onto the pointers below.

13.2. Pointer definition.


A pointer contains an address that points to data. An example of code defining a pointer is:
main()
{
int *Width;
}

A graphical representation could be...


(Address) (Data)
F1 <- ------ Width
F2
F3
F4 14

So far, this variable looks the same as above, the value stored at 'Width' is unknown. To place a value in 'Width' you
could code.
main()
{
int *Width;
*Width = 34;
}

(Address) (Data)
F1 00<- ------- Width
F2 00 (Data) (Address)
F3 00 *Width ---------- ->00 D1
F4 14 ------ 00 D2
00 D3
22 D4

Unlike the Length = 20 example above, the storage pointed to by 'Width' does NOT contain 34 (22 in Hex), it
contains the address where the value 34 can be found. The final program is...
main()
{
char *Width;

34
ANSI C Programming Reference Chapter 13:
*Width = 34;

printf(" Data stored at *Width is %d\n", *Width);


printf(" Address of Width is %p\n", &Width);
printf("Address stored at Width is %p\n", Width);
}

The program would print out something like.


Data stored at *Width is 34
Address of Width is 0xF1
Address stored at Width is 0xD1

A pointer can point to any data type, ie int, float, char. When defining a pointer you place an * (asterisk) character
between the data type and the variable name, here are a few examples.
main()
{
int count; /* an integer variable */
int *pcount; /* a pointer to an integer variable */
float miles; /* a floating point variable. */
float *m; /* a pointer */
char ans; /* character variable */
char *charpointer; /* pointer to a character variable */
}

13.3. Pointers to arrays


When looking at arrays we had a problem accessing the data within a two dimensional character array. This is what
the code looked like.
main()
{
char colours[][6]={"red","green","blue"};
}
The code above has defined 3 arrays, each containing 6 character strings. We can access the individual characters
with the following syntax.
printf ("%c \n", colours[0][0]);

but can't extract a whole string. By using pointers as below, we can.


main()
{
char *colours[]={"red","green","blue"};
}
This now defines an array of 3 pointers, all pointing to storage locations. So
printf("%s \n", colours[1]);
will return green.

13.4. Char Arrays versus Char pointers


What is the difference between these to lumps of code?

main() main()
{ {
char colour[]="red"; char *colour="red";
printf("%s \n",colour); printf("%s \n",colour);
} }

The answer is, not a great deal, at first sight! They both print the word red because in both cases 'printf' is being
passed a pointer to a string. The difference is on how the pointer is defined.

• On the left, an array of 10 bytes is defined.


• On the right a pointer to storage is defined.
• In both cases 'colour' is a pointer.
• On the left 'colour' is a pointer to 'colour[0]'.
• On the right 'colour' is a pointer to a storage location.
The pointer can also point to dynamically allocated memory. See the malloc function for details.

35
ANSI C Programming Reference Chapter 13:

13.5. Void Pointers


There are times when you write a function but do not know the datatype of the returned value. When this is the case,
you can use a void pointer.

13.6. Pointers to functions


 Example:
/* Purpose: 1. Define a pointer to a function.
* 2. Point at a function.
* 3. Execute the function.*/

int (*fpointer)(void); /* Define a pointer to a function */


int func1(void); /* Define a few functions. */
int func2(void);

main()
{
fpointer = func1; /* Put the address of 'func1' in 'fpointer' */
fpointer(); /* Execute 'func1' */
fpointer = func2; /* Repeat for 'func2' */
fpointer();
}

int func1(void)
{
puts("martin was ere");
}

int func2(void)
{
puts("alex was ere");
}

13.7. Linked Lists


Question: How would you write a program to meet the following requirements?
1. Read an unknown number of records from a file into memory. A typical record would look like:
Ref Title Cost
--- ----- ----
1234 Oracle_Guide 22.95
2. Perform a numeric sort based on the first field.
3. Delete duplicate records based on the first field.

One method is to define an array of records as shown below:


main()
{
char array[50][80]; /* 50 records, 80 bytes long */
}
The data can first be read into the array and then actions performed on the data. This is in principle OK but has some
major problems.

36
ANSI C Programming Reference Chapter 14:
1. The arrary will hold all the data in character format. It
would be nice to hold the integer and decimal numbers in
a more appropriate form. Name Age Pointer
2. If you have more than 50 records the program has to be
altered and recompiled.
The first problem could be fixed by defining an

array of structures BUT both problems can be solved with Name Age Pointer
linked lists.
The concept of a linked list is fairly simple. It is a group of
structures linked together by pointers, as shown in the figure

to the right. NULL
The "Name Age Pointer" block could be defined as below:
struct record {char name[20]; int age; struct record *next_rec;};
The important bit is "struct record *next_rec" this is the pointer to the next structure (record). It will either point to
the next record which will require memory reserved with the malloc function or NULL if its the last record.

 See Also:
VOID keyword. - function arguments - Strings - Arrays.

13.8. The malloc function


malloc (memory allocation) is used to dynamically allocate memory at run time. Possible uses for this function are:

• Read records of an unknown length.


• Read an unknown number of database records.
• Link lists.
The simplest way to reserve memory is to code something like:
main()
{
char string[1000];

strcpy (string, "Some text");


}
The example above has two problems:

• If the data is less than 1000 bytes we are wasting memory.


• If the data is greater than 1000 bytes the program is going to crash.
• The 1000 bytes are reserved throught out the life of the program. If this was a long running program that rarely
used the memory ,it would again be waistfull.
malloc allows us to allocate exactly the correct amount of memory and with the use of free only for the time it is
required.

 Example:
Library: stdlib.h
Prototype: void *malloc(size_t size);
Syntax: char * String;

String = (char *) malloc(1000);


Looking at the example syntax above, 1000 bytes are reserved and the pointer String points to the first byte. The
1000 bytes are NOT initialized by malloc. If the memory is NOT available, a NULL pointer is returned. Please note,
the cast cast is required to return a pointer of the correct type.

 C++ equivalents
new is the C++ equivalent to malloc.
delete is the C++ equivalent to free.

14. Strings and Characters

37
ANSI C Programming Reference Chapter 14:

14.1. Pointers to strings.


C does not have a "string" datatype. To create a string you have to use a char array or a char pointer. If you are not
familur with char arrays I recomend that you read about them now. To recap, a char pointer is defined like this:
main()
{
char *Text;
}
All this program does is reserve storage that will hold an address. At this point the address could be anything. To
initalize Text you can code:
main()
{
char *Text = "Thunder";
}
Text now has the address of the first character in Thunder. Graphically, things look like this.
(Address) (Data)
F1 00<- ------- Text
F2 D1 (Data) (Address)
F3 00 * Text ----- >54 (T) D1
F4 D1 ------ 68 (h) D2
75 (u) D3
6E (n) D4
64 (d) D5
65 (e) D6
72 (r) D7
00 D8

Please note the 00 at the end of Thunder. This is the NULL character and is used to mark the end of a string.
If we wanted to O/P the data pointed to by a char pointer we can code.
Source:
main()
{
char *Text1 = "Thunder"; /* Define and initalize */
char *Text2; /* Define only */

Text2 = "Bird"; /* Point to some text */

printf("%s%s\n", Text1, Text2);


}
Result:
ThunderBird
This is all very well, but there is a MAJOR problem! Thunder and Bird are constants, they cannot be changed in
anyway. We need a method of pointing to some storage that can be altered and true to form, C provides a function
called malloc to do just that.

14.2. printf, sprintf, fprintf, scanf format identifiers.


%d %i Decimal signed integer.
%o Octal integer.
%x %X Hex integer.
%u Unsigned integer.
%c Character.
%s String. See below.
%f double
%e %E double.
%g %G double.
%p pointer.
%n Number of characters written by this printf.
No argument expected.
%% %. No argument expected.

I. Except for %% and %n, all the identifiers expect to extract an argument from the printf parameter list.
II. All of the parmameters should be the value to be inserted. EXCEPT %s, this expects a pointer to be passed.

38
ANSI C Programming Reference Chapter 14:

 Example.
main()
{
int number=5;
char *pointer="little";
printf("Here is a number %d and a %s word.\n", number, pointer);
}
/*********************************
* Program result is: */
Here is a number 5 and a little word.

 Field width.
By default the width of a field will be the minimum required to hold the data. In the example above the width of %s
becomes 6. If you want to control the field width you can use the following syntax.
main()
{
int number=5;
char *pointer="little";

printf("Here is a number-%4d-and a-%10s-word.\n", number, pointer);


}
/*********************************
* Program result is: */
Here is a number- 5-and a- little-word.
As you can see, the data is right justified within the field. There is one other version of the field width that is used
with floating point numbers.
%8.2f
This says you require a total field of 8 characters, within the 8 characters the last 2 will hold the decimal part.

 Flags
The format identifers can be altered from their default function by applying the following flags:
- Left justify.
0 Field is padded with 0's instead of blanks.
+ Sign of number always O/P.
blank Positive values begin with a blank.
# Various uses:
%#o (Octal) 0 prefix inserted.
%#x (Hex) 0x prefix added to non-zero values.
%#X (Hex) 0X prefix added to non-zero values.
%#e Always show the decimal point.
%#E Always show the decimal point.
%#f Always show the decimal point.
%#g Always show the decimal point, trailing zeros not removed.
%#G Always show the decimal point, trailing zeros not removed.

I. The flags are placed between the % and the field width or format identifier.
II. Where it make sense, more than one flag can be used.
Here are a few more examples.
printf(" %-10d \n", number);
printf(" %010d \n", number);
printf(" %-#10x \n", number);
printf(" %#x \n", number);

14.3. Escape sequences.


\n Newline
\t Horizontal Tab
\v Vertical Tab
\b Backspace
\r Carriage Return
\f Form feed
\a Audible Alert (bell)
\\ Backslash
\? Question mark
\' Single quote
\" Double quote
\000 Oct - No one uses Octal unless they have an ICL background...

39
ANSI C Programming Reference Chapter 15:
\xhh Hex number
\ Preprocessor line continuation, must be immediately followed by \n.
These can be used anywhere that C expects to see a character constant. Must be time for a quick example.
main()
{
char word[]="\x6d\x6f\x64\x65\x6d";

printf("%s\n", word);
}
Can you work out what will appear if you run this program??

14.4. Ascii character table in Hex.

00 01 02 03 04 05 06 07
08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17
18 19 1A 1B 1C 1D 1E 1F
20 21 ! 22 " 23 # 24 $ 25 % 26 & 27 '
28 ( 29 ) 2A * 2B + 2C , 2D - 2E . 2F /
30 0 31 1 32 2 33 3 34 4 35 5 36 6 37 7
38 8 39 9 3A : 3B ; 3C C 3D = 3E > 3F ?
40 @ 41 A 42 B 43 C 44 D 45 E 46 F 47 G
48 H 49 I 4A J 4B K 4C L 4D M 4E N 4F O
50 P 51 Q 52 R 53 S 54 T 55 U 56 V 57 W
58 X 59 Y 5A Z 5B [ 5C \ 5D ] 5E ^ 5F _
60 ` 61 a 62 b 63 c 64 d 65 e 66 f 67 g
68 h 69 i 6A j 6B k 6C l 6D m 6E n 6F o
70 p 71 q 72 r 73 s 74 t 75 u 76 v 77 w
78 x 79 y 7A z 7B { 7C | 7D } 7E ~ 7F

15. Functions Summary


15.1. ANSI standard libraries.
The ANSI library is declared in the following header files.
assert.h ctype.h errno.h float.h limits.h locale.h math.h setjmp.h signal.h stdarg.h stddef.h stdio.h
stdlib.h string.h time.h

15.2. ctype.h
isalnum Checks whether a character is alphanumeric (A-Z, a-z, 0-9)
isalpha
iscntrl Checks whether a character is a control character or delete ( decimal 0-31 and 127)
isdigit Checks whether a character is a digit (0-9)
isgraph Checks whether a character is a printable character, excluding the space (decimal 32)
islower Checks whether a character is a lower case letter (a-z).
isprint Checks whether a character is printable (decimal 32-126).
ispunct Checks whether a character is punctuation (decimal 32-47, 58-63, 91-96, 123-126)
isspace Checks whether a character is white space - space, CR HT VT NL, FF.
isupper Checks whether a character is an upper case letter (A-Z).
isxdigit Checks whether a character is hex digit (0-9, A-F, a-f).
toupper Converts a lowercase character to uppercase. int toupper(int c)
tolower Convert an uppercase character to lowercase. int tolower(int c)

40
ANSI C Programming Reference Chapter 15:

15.3. math.h
acos asin atan atan2 cos sin tan cosh sinh tanh exp frexp ldexp log log10 modf pow sqrt ceil fabs
floor fmod
Note! For some reason abs is in stdlib.h

15.4. stdio.h
This header defines all the ANSI I/O functions that allow you to read and write to files and devices. Low level (non
ANSI) functions are also available.
rename remove tmpfile tmpnam fflush freopen setbuf setvbuf fscanf vfprintf vprintf vsprintf scanf
ungetc fread fwrite fgetpos fseek fsetpos ftell rewind clearerr fseek

fclose Close a file.


fopen Open a file
fgetc Read a character from a file.
feof Check for EOF while reading a file.
fgets Read a record from a file (safer than fgetc).
fprintf O/P a line of data to a file.
fputc Put a charater into a file.
fputs Put a string into a file.
printf O/P data to the screen or a file.
sprintf O/P data in tha same way as 'printf' but put it into a string.
getc Get a character from an input stream.
getchar Get a character from the keyboard (STDIN).
gets Get string (from keyboard).
putchar O/P a character to STDOUT.
puts O/P data to the screen or a file.
sscanf Extract fields from a string.

15.5. stdlib.h
abort abs atexit atof atol calloc div exit labs ldiv mblen mbstowcs mbtowc realloc strtod strtoul
wctomb wcstombs
atoi Accepts +-0123456789 leading blanks and converts to integer.
bsearch Binary chop.
getenv Get an environmental variable.
free memory allocated with malloc.
malloc dynamically allocate memory.
qsort Sort an array.
rand Generate a random number.
strtol String to long integer conversion. Takes data in various number bases.
srand Seed a random number.
system Issue a command to the operating system

15.6. string.h
memchr memcmp memcpy memmove memset strcoll strcspn strerror strlen strncat strncmp strpbrk
strspn strxfrm
strcpy Copy strings.
strcat Concatinate two strings.
strchr Search for a character in a string.
strcmp Compare strings.
strncpy Copy part of a string.
strrchr Search for a character in a string.

41
ANSI C Programming Reference Chapter 16:
strstr Search a string for a substring.
strtok The books say this function splits a string into tokens. I think its function is best described as parsing a string.

15.7. time.h
asctime clock ctime difftime gmtime localtime mktime strftime time

16. C Programming Examples


All the below examples and many more may be found on:
http://www.jaxnet.com/~garyg/C_ref/C/EXAMPLES/examples.html

They have been tested on a PC running Linux and using the 'gcc' compiler. You can extract the programs with the
'save' option under 'file' and compile with your own compiler.

Your first C program.


if.
while.
do.
for example 1. for A more advanced example.
switch.
function.
Global and local variables.
Increment & decrement.
Pass command line arguments.
Print from 10 to 1 - three examples.
Read a file - version 1.
manipulate strings.
Using 'curses' to read a password.
Programs requiring X. Unix users only.

Index of all example programs.


O'Reillys' Using C examples.
O'Reillys' Practical C examples.
Bob Stouts 'Snippets'.

42
ANSI C Programming Reference Chapter 17:

17. Glossary of C Terms.


Address. Reference to a memory location. In C pointers are used to hold addresses.
Argument. A value passed to a function (see parameter).
Block. A sequence of definitions, declarations and statements, enclosed within braces {}.
Character Array. A set of elements of type char. (Can be used to store a string).
Class C++ term, not used in ANSI C.
Compilation error. Error which occurs during the translation of source code into machine code.
Compiler. A program which converts source code into machine code.
Compound Statement. A sequence of simple statements.
Constant An item that represents a value that cannot be changed. For Example:
(common all garden) 123
'x'
Constant (symbolic) A symbol defined in a #define preprocessor directive to represent a constant value.
Data type. Definition of the data. int, char, float.
Declaration. A construct which associates attributes to a variable name or function.
No storage is reserved.
For example:
extrn int a;
extrn char c;
variable declaration
A structure declaration could look like:
struct per_rec
{
int age;
char * surname;
char * firstname;
};
Definition.

1. Variable definition is a declaration with storage allocation.


int a;
char c;
struct per_rec person;

2. A construct which specifies the name,parameters and return type of a function.


For example a function definition would be:
long sqr(int num)
{
return(num*num);
}
Escape sequence. Control codes comprising combinations of a backslash followed by letters or digits which represent
non printing characters.
Executable program. Program which will run in the environment of the operating system or within an appropriate run time
environment.
Executable (stand-alone) Program which will run within the environment of the operating system without
program. additional utilities or support.
Expression. A sequence of operators and operands which may yield a single value.
File. Data stored as an electronic file.
File descriptor. This is used in low level I/O (open/read/write/close functions) to identify a file. It is an integer
number assigned to a file name by open and then used as a unique identifier by read/write and close.
Floating-point Number. Number having a decimal place or exponent.
Format specification. A string which controls how input or output shall be presented.

43
ANSI C Programming Reference Chapter 17:
Identifier. The names used to refer to stored data values such as constants, variables or functions.
Integer. A number without a fractional part.
Keyword. A word which has a predefined meaning to a 'C' compiler and therefore must not be used for any
other purpose.
library file. The file which contains compiled versions of commonly used functions which can be linked to an
object file to make an executable program.
Library function. A function whose code is contained in the external library file.
Line. One line of input from the standard input device (keyboard) which is terminated with a newline
character. The newline character is replaced by a null character.
Literal. Characters, letters or strings which are to be taken literally and used as constants rather than
identifiers.
Object C++ term, not used in ANSI C.
Object Code. Code which is directly understandable by the machine (machine code).
Operand. An expression acted on by an operator. For example:
z = a + b;
a and b are both operands of the + operator.
Parameter. A value received by a function.
Pointer. Variable containing an address.
Polymorphism C++ term, not used in ANSI C.
Precedence (of operators) The order in which operators are dealt with during the evaluation of an expression.
Preprocessor. A processor which manipulates the initial directives of the source file which contains instructions
about how the source file shall be processed and compiled.
Preprocessor directive. Source file instruction about how the file shall be processed and compiled.
Program. A text file comprising code which can be compiled.
Run time error. An error which occurs when a program is executed.
Reserved word Same as keyword. A word which has a predefined meaning to a 'C' compiler and therefore must not
be used for any other purpose.
Scope.
Source code. A text file comprising code which can be compiled.
Statement. A simple statement is an expression followed by a semicolon. (See compound statement and block).
String. A string in 'C' is an array of characters terminated by a Null character ('\0').
Syntax error. A mistake in the source code which prevents the compiler from converting it into object code.
Variable. An identifier (and storage) for a data type and for which the data value is allowed to change as the
program runs.

44

You might also like