You are on page 1of 44

ANSI C Programming Reference.

ANSI C Programming Reference

Chapter 0:

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

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

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

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
auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while

Chapter
Storage Class Keyword Flow Control Keywords Flow Control Keywords Data Type Keywords Data Type Keywords Flow Control Keywords Flow Control Keywords Loop Control Keywords Data Type Keywords Flow Control Keywords Data Type Keywords Storage Class Keyword Data Type Keywords Loop Control Keywords Flow Control Keywords Flow Control Keywords Data Type Keywords Data Type Keywords - Modifiers Storage Class Keyword Flow Control Keywords Data Type Keywords - Modifiers Data Type Keywords - Modifiers Data Type Keywords Storage Class Keyword The STRUCT Keyword Flow Control Keywords Storage Class Keyword Storage Class Keyword Data Type Keywords - Modifiers Data Type Keywords Data Type Keywords Loop Control Keywords

Section Page
6.1 3.1 3.2 2.5 2.9 3.3 3.2 4.2 2.4 3.4 2.8 6.4 2.3 4.3 3.5 3.4 2.2 2.6 6.2 3.6 2.6 2.6 2.13 6.3 5 3.2 6.5 6.6 2.6 2.7 2.10 4.4 19 10 10 6 8 11 10 14 6 11 7 20 6 14 12 11 6 6 19 13 6 6 9 19 16 10 20 20 6 7 8 16

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 <= float <= int double < <= long int 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:

ANSI C Programming Reference


short int int int long int signed char unsigned char float double long double 2 2 4 1 1 4 8 8 bytes bytes bytes byte byte bytes bytes bytes (16 bits) (16 bits) (32 bits) (Range -128 ... +127) (Range 0 ... 255)

Chapter 2:

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);

ANSI C Programming Reference


} /*************** Resulting printout: ******************/ False has a value of 1 True has a value of 1

Chapter 2:

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:

ANSI C Programming Reference


main() { int var1; float var2; var2 = (float)var1; }

Chapter 3:

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

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: [case constant-expression2: [case constant-expression3: [default : statements4;] } statements1; statements2;] statements3;]

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' : case 'B' : case 'C' : case 'D' : case 'F' : default : } ) printf( printf( printf( printf( printf( printf( "Excellent" ); "Good" ); "OK" ); "Mmmmm...." ); "You must do better than this" ); "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]; FILE *ptr;

/* Record read from the file. /* Pointer to the file. FILE is a structure defined in <stdio.h>

*/ */

10

ANSI C Programming Reference


/* 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. }

Chapter 3:

*/

*/ */ */ */

3.4. The if and else keywords


The if-else statement is a two-way decision statement. It is written as
if ( expression ) [else statement1; 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 ) else larger = a; larger = b; /* else part is present */

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


{ CheckDate(40) } void CheckDate(int Month) { if (Month > 31) { return; } puts("Month is valid"); }

Chapter 4:

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


do { printf(" i is %d\n", i); } while(--i); }

Chapter 4:

The program result will look like this:


i i i i i is is is is is 5 4 3 2 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", printf("%d\n", printf("%d\n", printf("%d\n", printf("%d\n", }

count++); count++); count++); count++); 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


for (expression_1 ; expression_2 ; expression_3) statement ;

Chapter 4:

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 i i i is is is is 4 3 2 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 Harry Billy Loss Carpenter King Maths English Maths A A 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;}; struct {int a; int b; int c;} z; struct x z; /* declaration */

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;} ; void function(struct x); main() { struct x z; z.a = 10; z.a++; /* 1 */ | | | | | | | | | | | | | | | | struct x {int a; int b; int c;} ; void function(struct x *); main() { struct x z, *pz; pz = &z; z.a = 10; z.a++;

/* 3 */ /* 4 */

function(z); /* 2 */ } void function( struct x z) { printf(" first member %d \n", z.a); }

function(pz); /* 5 */ } void function(struct x * pz) { /* 6 */ 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;} ; void function(struct x * ); main() { /* Declare two variables: *z == type struct x and * pz == a pointer to type struct x */ struct x z, *pz; pz = &z; z.a = 10; z.a++; /* put the address of 'z' into 'pz' */ /* initialize z.a */ /* Increment z.a */ /* Declare the structure.*/ /* Declare the function. */

/* 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 printf(" first member after printf(" first member after printf(" first member after } NEW the the the value of function function function 'z.a' using three different notations */ call %d \n", pz->a); call %d \n", (*pz).a); 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


main() { char *Text1; Text1 = func(); } char * func(void) { char Text2[10]="martin"; return(Text2); }

Chapter 6:

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 -------extern int count; write() { printf("count is %d\n", count); } | | | | | | | | Source 2 -------int count=5; main() { 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() { int money; money = 2; } | | | | | | main() { typedef int Pounds; 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) { int c; c = a + b; return c; } /* Function definition */

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; /* a comment */ /* * Another comment */ /***************** * * Final comment. * *****************/ } /* Initalise Counter */

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); } if (j > 0) { int i=100; printf("i is %d\n",i); } printf("i is %d\n",i); }

/* i defined in 'main' can be seen

*/

/* 'i' defined in and local to this block */ /* 'i' (value 100) dies here /* 'i' (value 5) is now visible. */ */

7.7. Global variables


Global variables ARE initalised by the system when you define them!
int char float pointer == == == == 0 \0 0 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; main() { i++; func } func() { int i=10; i++; } /* Global definition /* global variable */ */

/* Internal declaration */ /* 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); main() { /* Function declaration */

23

ANSI C Programming Reference


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) { int c; c = a + b; return c; } /* Function definition */ */

Chapter 8:

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*); main() { int i=4; int* ptr; ptr = &i; /* variable declaration */ /* int pointer */ /* 'ptr' now contains the address of 'i'*/ /* Function declaration */

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) { ++*ptr; return; }

*/

/* Function definition */ /* Add 1 to the value pointed too by 'ptr' */

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


++*ptr; ++*(ptr+1); return; } /* Add 1 to the first element in the array */ /* And the second element */

Chapter 9:

/* (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); printf("%s\n", array1); } function1(char * array) { printf("%s\n", array); array +=4; *array = 'x'; } /* call function

*/ */

/* O/P the altered array. '5' will * have been changed to 'x' */

/* printf expects a pointer. /* Modify the pointer. /* 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) (1 != 1) (i = 1) (i = 0) (i = 1 + 1) true false true false 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


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.

Chapter 9:

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:
<= >= == != More Bitwise & ^ | && || ?: = += -= *= /= %= &= ^= |= <<= >>= , Less than or equal to. Greater than or equal to. Equal to. Not equal to. bitwise AND bitwise Excusive OR bitwise OR Logical AND Logical OR Conditional construct. Equals assignment assignment assignment assignment assignment assignment assignment assignment assignment assignment Comma

Detailed precedence table


All operators in the same block have the same precedence. The first block has the highest precedence. Group
Membership.

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

Description
Function call. Array. Structure pointer. Structure member. Logical NOT Assignment Increment. Decrement. Logical. Logical. Conditional

Unary.

Pointer to data Address of a variable. type cast. Multiply. Divide. Modulo. Addition Subtraction. Shift left. Shift Right. Less than. Greater than.

Binary

Series

Binary

Bitwise

Relational

10. Bitwise operations


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

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; unsigned int b = 13; unsigned int c = 0; c = a & b; } /* 60 = 0011 1100 */ /* 13 = 0000 1101 */ /* 12 = 0000 1100 */

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


main()

ANSI C Programming Reference


{ unsigned int a = 60; unsigned int b = 13; unsigned int c = 0; c = a | b; } /* 60 = 0011 1100 */ /* 13 = 0000 1101 */ /* 61 = 0011 1101 */

Chapter 11:

XOR ^ copies the bit if it is set in one operand (but not both).
main() { unsigned int a = 60; unsigned int b = 13; unsigned int c = 0; c = a ^ b; } /* 60 = 0011 1100 */ /* 13 = 0000 1101 */ /* 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; Value = ~ Value; }

/*

4 = 0000 0100 */

/* 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; unsigned int Shift=2; Value = Value << Shift; Value <<= Shift; Printf("%d\n", Value); /* 4 = 0000 0100 */

/* 16 = 0001 0000 */ /* 64 = 0100 0000 */ /* 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; i=1234; i++; /* /* * /* declare a variable called 'i' assign the constant value 1234 to the variable '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


0xff 0100 '\xf' (Hexidecimal) (Octal) (Hex character) /* i assigned the decimal value of 255 /* subtract 255 from i*/ /* Add Octal 10 (decimal 8) */ */

Chapter 12:

Examples of their use are:


int i=255; i-=0xff i+=010

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 1234U 1234UL /* Long int constant (4 bytes) /* Unsigned int /* Unsigned long int */ */ */

The other modifier is 'U' for Unsigned. and to complete the picture you can specify 'UL'

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; float miles; } /* interger variable /* floating point variable */ */

31

ANSI C Programming Reference


The syntax for an array is:
main() { int count[5]; float miles[10]; } /* interger 5 element array */ /* floating point 10 element array */

Chapter 12:

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, {3, {5, {7, } 2}, 4}, 6}, 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


main() { char letter='x'; char letters[10]='f','a','x',' ','m','o','d','e','m','\0'; char text[10]="fax modem"; }

Chapter 13:

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 F2 F3 F4 <- ------ Length

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

33

ANSI C Programming Reference


main() { int Length; Length = 20; }

Chapter 13:

the decimal value 20 (Hex 14) is placed into the storage location.
(Address) (Data) F1 F2 F3 F4 <- ------ Length

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 F2 F3 F4 <- ------ Width

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 F2 F3 F4 00<- ------- Width 00 00 14 (Data) (Address) D1 D2 D3 D4

*Width ---------- ->00 -----00 00 22

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


*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); }

Chapter 13:

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; int *pcount; float miles; float *m; char ans; char *charpointer; } /* /* /* /* /* /* an integer variable a pointer to an integer variable a floating point variable. a pointer character variable 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() { char colour[]="red"; printf("%s \n",colour); } main() { char *colour="red"; 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); int func1(void); int func2(void); main() { fpointer = func1; fpointer(); fpointer = func2; fpointer(); } int func1(void) { puts("martin was ere"); } int func2(void) { puts("alex was ere"); } /* Define a pointer to a function /* Define a few functions. */ */

/* Put the address of 'func1' in 'fpointer' */ /* Execute 'func1' */ /* Repeat for 'func2' */

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


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. 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 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. The "Name Age Pointer" block could be defined as below:

Chapter 14:

Name Age Pointer

Name Age Pointer

NULL

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 F2 F3 F4 00<- ------- Text D1 (Data) (Address) 00 D1 * Text ----- >54 (T) -----68 (h) 75 (u) 6E (n) 64 (d) 65 (e) 72 (r) 00 D1 D2 D3 D4 D5 D6 D7 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"; char *Text2; Text2 = "Bird"; printf("%s%s\n", Text1, Text2); } /* Define and initalize */ /* Define only */ /* Point to some text */

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

I. II.

Except for %% and %n, all the identifiers expect to extract an argument from the printf parameter list. 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 number5-and alittle-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:
0 + blank # %#o (Octal) %#x (Hex) %#X (Hex) %#e %#E %#f %#g %#G Left justify. Field is padded with 0's instead of blanks. Sign of number always O/P. Positive values begin with a blank. Various uses: 0 prefix inserted. 0x prefix added to non-zero values. 0X prefix added to non-zero values. Always show the decimal point. Always show the decimal point. Always show the decimal point. Always show the decimal point, trailing zeros not removed. 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(" printf(" printf(" printf(" %-10d \n", number); %010d \n", number); %-#10x \n", number); %#x \n", number);

14.3. Escape sequences.


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

39

ANSI C Programming Reference


\xhh \

Chapter 15:

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 08 10 18 20 28 30 38 40 48 50 58 60 68 70 78 01 09 11 19 21 29 31 39 41 49 51 59 61 69 71 79 02 0A 12 1A 22 2A 32 3A 42 4A 52 5A 62 6A 72 7A 03 0B 13 1B 23 2B 33 3B 43 4B 53 5B 63 6B 73 7B 04 0C 14 1C 24 2C 34 3C 44 4C 54 5C 64 6C 74 7C 05 0D 15 1D 25 2D 35 3D 45 4D 55 5D 65 6D 75 7D 06 0E 16 1E 26 2E 36 3E 46 4E 56 5E 66 6E 76 7E 07 0F 17 1F 27 2F 37 3F 47 4F 57 5F 67 6F 77 7F

( 0 8 @ H P X ` h p x

! ) 1 9 A I Q Y a i q y

" * 2 : B J R Z b j r z

# + 3 ; C K S [ c k s {

$ , 4 C D L T \ d l t |

% 5 = E M U ] e m u }

& . 6 > F N V ^ f n v ~

' / 7 ? G O W _ g o w

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. Argument. Block. Character Array. Class Compilation error. Compiler. Compound Statement. Constant (common all garden) Constant (symbolic) Data type. Declaration. Reference to a memory location. In C pointers are used to hold addresses. A value passed to a function (see parameter). A sequence of definitions, declarations and statements, enclosed within braces {}. A set of elements of type char. (Can be used to store a string). C++ term, not used in ANSI C. Error which occurs during the translation of source code into machine code. A program which converts source code into machine code. A sequence of simple statements. An item that represents a value that cannot be changed. For Example: 123 'x' A symbol defined in a #define preprocessor directive to represent a constant value. Definition of the data. int, char, float. 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. Executable program.

Control codes comprising combinations of a backslash followed by letters or digits which represent non printing characters. 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. File. File descriptor. A sequence of operators and operands which may yield a single value. Data stored as an electronic file. 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


Identifier. Integer. Keyword. library file. Library function. Line. Literal. Object Object Code. Operand. A number without a fractional part.

Chapter 17:

The names used to refer to stored data values such as constants, variables or functions.

A word which has a predefined meaning to a 'C' compiler and therefore must not be used for any other purpose. The file which contains compiled versions of commonly used functions which can be linked to an object file to make an executable program. A function whose code is contained in the external library file. 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. Characters, letters or strings which are to be taken literally and used as constants rather than identifiers. C++ term, not used in ANSI C. Code which is directly understandable by the machine (machine code). An expression acted on by an operator. For example: z = a + b; a and b are both operands of the + operator.

Parameter. Pointer. Polymorphism

A value received by a function. Variable containing an address. 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. Preprocessor directive. Program. Run time error. Reserved word Scope. Source code. Statement. String. Syntax error. Variable. A text file comprising code which can be compiled. A simple statement is an expression followed by a semicolon. (See compound statement and block). A string in 'C' is an array of characters terminated by a Null character ('\0'). A mistake in the source code which prevents the compiler from converting it into object code. An identifier (and storage) for a data type and for which the data value is allowed to change as the program runs. A processor which manipulates the initial directives of the source file which contains instructions about how the source file shall be processed and compiled. Source file instruction about how the file shall be processed and compiled. A text file comprising code which can be compiled. An error which occurs when a program is executed. Same as keyword. A word which has a predefined meaning to a 'C' compiler and therefore must not be used for any other purpose.

44

You might also like