Preprocessor
In C language, all preprocessor directives begin with the hash character (#). You can see one preprocessor directive in "Hello, World!": #include.
#include
C Structure and Style
This is a basic introduction to producing effective code structure in the C Programming Language. It is designed to provide information on how to effectively use indentations, comments, and other elements that will make your C code more readable. It is not a tutorial on actually programming in C.
New programmers will often not see the point of creating structure in their programs' code, because they often think that code is designed purely for a compiler to read. This is often not the case, because well-written code that follows a well-designed structure is usually much easier for programmers (who haven't worked on the code for months) to read, and edit.
In the following sections, we will attempt to explain good programming techniques that will in turn make your programs more effective.
Introduction
The following two blocks of code are essentially the same: Both of them contain exactly the same code, and will compile and execute with the same result; however there is one essential difference.
Which of the following programs do you think is easier to read?
#include
int main(void) {printf("Hello, World!\n");return 0;}
or
#include
int main(void)
{
printf("Hello, World!\n");
return 0;
}
The simple use of indents and line breaks can greatly improve the readability of the code; without making any impact whatsoever on how the code performs. By having readable code, it is much easier to see where functions and procedures end, and which lines are part of which loops and procedures.
This book is going to focus on the above piece of code, and how to improve it. Please note that during the course of the tutorial, there will be many (apparently) redundant pieces of code added. These are only added to provide examples of techniques that we will be explaining, without breaking the overall flow of code that the program achieves.
Line Breaks and Indentation
The addition of white space inside your code is arguably the most important part of good code structure. Effective use of it can create a visual gauge of how your code flows, which can be very important when returning to your code when you want to maintain it.
Line Breaks
10 #include
20 int main(void){ int i=0; printf("Hello, World!"); for (i=0; i<1;>
Rather than putting everything on one line, it is much more readable to break up long lines so that each statement and each declaration goes on its own line.
blank lines
Blank lines should be used in three main parts of your code
- After precompiler declarations.
- After new variables are declared.
- Between new paths of code. (i.e. Before the declaration of the function or loop, and after the closing '}' bracket).
Note that we have added line numbers to the start of the lines. Using these in actual code will make your compiler fail, they are only there for reference in this book.
#include
int main(void)
{
int i=0;
printf("Hello, World!");
for (i=0; i<1;i++{printf("\n");break;}return 0;}
Based on the rules we established earlier, there should now be four line breaks added.
- Between lines 10 and 20, as line 10 is a precompiler declaration
- Between lines 40 and 50, as the block above it contains variable declarations
- Between lines 50 and 60, as it is the beginning of a new path (the 'for' loop)
- Between lines 100 and 110, as it is the end of a path of code
This will make the code much more readable than it was before:
The following lines of code have line breaks between functions, but not any indention.
#include
int main(void)
{
int i=0;
printf("Hello, World!");
for (i=0; i<1;>{printf("\n");break;}
return 0;}
But this still isn't as readable as it can be.
Indentation
Although adding simple line breaks between key blocks of code can make code marginally easier to read, it provides no gauge of the flow of the program. The use of your tab key can be very useful now: indentation visually separates paths of code by moving their starting points to a new column in the line. This simple practice will make it much easier to read code. Indentation follows a fairly simple rule:
- All code inside a new path (i.e. Between the two '{' brackets '}') should be indented by one tab more than the code in the previous path.
So, based on our code from the previous section, there are two paths that require indentation:
- Lines 40 to 100
- Lines 70 and 80
#include
int main(void)
{
int i=0;
printf("Hello, World!");
for (i=0; i<1;>{printf("\n");break;}return 0;}
It is now fairly obvious as to which parts of the program fit inside which paths of code. You can tell which parts of the program will loop, and which ones will not. Although it might not be immediately noticeable, once many nested loops and paths get added to the structure of the program, the use of indentation can be very important.
NOTE: Many text editors automatically indent appropriately when you hit the enter/return key.
Comments
Comments in code can be useful for a variety of purposes. They provide the easiest way to point out specific parts of code (and their purpose); as well as providing a visual "split" between various parts of your code. Having a good commentary throughout your code will make it much easier to remember what specific parts of your code do.
Comments in modern flavours of C (and many other languages) can come in two forms:
//Single Line Comments
and
/*Multi-Line
Comments*/
| Note that Single line comments are only a very recent addition to C, and that some compilers may not support them. A recent version of GCC will have no problems supporting them. |
This section is going to focus on the various uses of each form of commentary.
Single-line Comments
Single-line comments are most useful for simple 'side' notes that explain what certain parts of the code do. The best places to put these comments are next to variable declarations, and next to pieces of code that may need explanation.
Based on our previous program, there are two good places to place comments
- Line 40, to explain what 'int i' is going to do
- Line 80, to explain why there is a 'break' keyword.
This will make our program look something like
#include
int main(void)
{
int i=0; //Temporary variable used for 'for' loop.
printf("Hello, World!");
for (i=0; i<1;>{printf("\n");break; //Exits 'for' loop.}
return 0;}
Multi-line Comments
Multi-line comments are most useful for long explanations of code. They can be used as copyright/licensing notices, and they can also be used to explain the purpose of a path of code. This can be useful in two facets: They make your functions easier to understand, and they make it easier to spot errors in code (if you know what a path is supposed to do, then it is much easier to find the piece of code that is responsible).
As an example, suppose we had a program that was designed to print "Hello, World! " a certain number of times, on a certain number of lines. There would be many for loops in this program. For this example, we shall call the number of lines i, and the number of strings per line as j.
A good example of a multi-line comment that describes 'for' loop i's purpose would be:
/* For Loop (int i)
Loops the following procedure i times (for number of lines). Performs 'for' loop j on each loop,
and prints a new line at end of each loop.
*/
/***************************************
* This is a multi line comment *
* That is surrounded by a *
* *
***************************************/
This will allow any outside users of the program an easy way to understand what the code does, and how it works. It also prevents confusion with other like-named functions.
Variables
Like most programming languages, C is able to use and process named variables and their contents. Variables are simply names used to refer to some location in memory - a location that holds a value with which we are working.
There are five basic data types associated with variables:
- int - integer: a whole number.
- float - floating point value: ie a number with a fractional part.
- double - a double-precision floating point value.
- char - a single character.
- void - valueless special purpose type which we will examine closely in later sections.
Declaring, Initializing, and Assigning Variables
Here is an example of declaring an integer, which we've called some_number. (Note the semicolon at the end of the line; that is how your compiler separates one program statement from another.)
int some_number;
This statement means we're declaring some space for a variable called some_number, which will be used to store integer data. Note that we must specify the type of data that a variable will store. There are specific keywords to do this - we'll look at them in the next section.
Multiple variables can be declared with one statement, like this:
int anumber, anothernumber, yetanothernumber;
We can also declare and assign some content to a variable at the same time. This is called initialization because it is the "initial" time a value has been assigned to the variable:
int some_number=3;
Naming Variables
Variable names in C are made up of letters (upper and lower case) and digits. The underscore character ("_") is also permitted. Names must not begin with a digit. Unlike some languages (such as Perl and some BASIC dialects), C does not use any special prefix characters on variable names.
Some examples of valid (but not very descriptive) C variable names:
foo
Bar
BAZ
foo_bar
_foo42
_
QuUx
Some examples of invalid C variable names:
2foo (must not begin with a digit)
my foo (spaces not allowed in names)
$foo ($ not allowed -- only letters, digits, and _)
while (language keywords cannot be used as names)
The Four Basic Types
In Standard C there are four basic data types. They are int
, char
, float
, and double
.
The int
type
The int type stores integers in the form of "whole numbers". An integer is typically the size of one machine word, which on most modern home PCs is 32 bits (4 octets). Examples of literals are whole numbers (integers) such as 1,2,3, 10, 100... When int is 32 bits (4 octets), it can store any whole number (integer) between -2147483648 and 2147483647. A 32 bit word (number) has the possibility of representing 4294967296 numbers (2 to the power of 32).
If you want to declare a new int variable, use the int keyword. For example:
int numberOfStudents, i, j=5;
In this declaration we declare 3 variables, numberOfStudents, i and j, j here is assigned the literal 5.
The char
type
The char
type is capable of holding any member of the execution character set. It stores the same kind of data as an int
(i.e. integers), but always has a size of one byte. The size of a byte is specified by the macro CHAR_BIT
which specifies the number of bits in a char (byte). In standard C it never can be less than 8 bits. A variable of type char
is most often used to store character data, hence its name.
char letter1 = 'a';
The float
type
float
is short for Floating Point. It stores real numbers also, but is only one machine word in size. Therefore, it is used when less precision than a double provides is required. float
literals must be suffixed with F or f, otherwise they will be interpreted as doubles. Examples are: 3.1415926f, 4.0f, 6.022e+23f. float variables can be declared using the float keyword.
The double type
The double and float types are very similar. The float type allows you to store single-precision floating point numbers, while the double keyword allows you to store double-precision floating point numbers - real numbers, in other words, both integer and non-integer values. Its size is typically two machine words, or 8 bytes on most machines. Examples of double literals are 3.1415926535897932, 4.0, 6.022e+23 (scientific notation). If you use 4 instead of 4.0, the 4 will be interpreted as an int.
Data type modifiers
One can alter the data storage of any data type by preceding it with certain modifiers.
long and short are modifiers that make it possible for a data type to use either more or less memory. The int keyword need not follow the short and long keywords. This is most commonly the case. A short can be used where the values fall within a lesser range than that of an int, typically -32768 to 32767. A long can be used to contain an extended range of values. It is not guaranteed that a short uses less memory than an int, nor is it guaranteed that a long takes up more memory than an int. It is only guaranteed that sizeof(short) <= sizeof(int) <= sizeof(long). Typically a short is 2 bytes, an int is 4 bytes, and a long either 4 or 8 bytes.
In all of the types described above, one bit is used to indicate the sign (positive or negative) of a value. If you decide that a variable will never hold a negative value, you may use the unsigned modifier to use that one bit for storing other data, effectively doubling the range of values while mandating that those values be positive. The unsigned specifier also may be used without a trailing int, in which case the size defaults to that of an int. There is also a signed modifier which is the opposite, but it is not necessary, except for certain uses of char, and seldom used since all types (except char) are signed by default.
To use a modifier, just declare a variable with the data type and relevant modifiers:
unsigned short int usi; /* fully qualified - unsigned short int */
short si; /* short int */
unsigned long uli; /* unsigned long int */
Expressions and Operators
One reason for the power of C is its wide range of useful operators. An operator is a function which is applied to values to give a result. You should be familiar with operators such as +, -, /.
Arithmetic operators are the most common. Other operators are used for comparison of values, combination of logical states, and manipulation of individual binary digits. The binary operators are rather low level for so are not covered here.
Operators and values are combined to form expressions. The values produced by these expressions can be stored in variables, or used as a part of even larger expressions.
Assignment Statement
The easiest example of an expression is in the assignment statement. An expression is evaluated, and the result is saved in a variable. A simple example might look like
This assignment will save the value of the expression in variable y.
y = (m * x) + c
Arithmetic operators
Here are the most common arithmetic operators
*, / and % will be performed before + or - in any expression. Brackets can be used to force a different order of evaluation to this. Where division is performed between two integers, the result will be an integer, with remainder discarded. Modulo reduction is only meaningful between integers. If a program is ever required to divide a number by zero, this will cause an error, usually causing the program to crash.
Here are some arithmetic expressions used within assignment statements.
C has some operators which allow abbreviation of certain types of arithmetic assignment statements.
velocity = distance / time;
force = mass * acceleration;
count = count + 1;
These operations are usually very efficient. They can be combined with another expression.
Versions where the operator occurs before the variable name change the value of the variable before evaluating the expression, so
These can cause confusion if you try to do too many things on one command line. You are recommended to restrict your use of ++ and - to ensure that your programs stay readable.
Another shorthand notation is listed below
Type conversion
You can mix the types of values in your arithmetic expressions. char types will be treated as int. Otherwise where types of different size are involved, the result will usually be of the larger size, so a float and a double would produce a double result. Where integer and real types meet, the result will be a double.
There is usually no trouble in assigning a value to a variable of different type. The value will be preserved as expected except where;
- The variable is too small to hold the value. In this case it will be corrupted (this is bad).
- The variable is an integer type and is being assigned a real value. The value is rounded down. This is often done deliberately by the programmer.
Values passed as function arguments must be of the correct type. The function has no way of determining the type passed to it, so automatic conversion cannot take place. This can lead to corrupt results. The solution is to use a method called casting which temporarily disguises a value as a different type.
eg. The function sqrt finds the square root of a double.
int i = 256;
int root
Comparison
C has no special type to represent logical or boolean values. It improvises by using any of the integral types char, int, short, long, unsigned, with a value of 0 representing false and any other value representing true. It is rare for logical values to be stored in variables. They are usually generated as required by comparing two numeric values. This is where the comparison operators are used, they compare two numeric values and produce a logical result.
Note that == is used in comparisons and = is used in assignments. Comparison operators are used in expressions like the ones below.
x == y i > 10 a + b != c In the last example, all arithmetic is done before any comparison is made.These comparisons are most frequently used to control an if statement or a for or a while loop. These will be introduced in a later chapter.
The cast is made by putting the bracketed name of the required type just before the value. (double) in this example. The result of sqrt( (double) i); is also a double, but this is automatically converted to an int on assignment to root.
root = sqrt( (double) i);
Logical Connectors
These are the usual And, Or and Not operators.
They are frequently used to combine relational operators, for example
x <>= 10 In C these logical connectives employ a technique known as lazy evaluation. They evaluate their left hand operand, and then only evaluate the right hand one if this is required. Clearly false && anything is always false, true || anything is always true. In such cases the second test is not evaluated.Not operates on a single logical value, its effect is to reverse its state. Here is an example of its use.
if ( ! acceptable ) printf("Not Acceptable !!\n");Control Statements
A program consists of a number of statements which are usually executed in sequence. Programs can be much more powerful if we can control the order in which statements are run.
Statements fall into three general types;
- Assignment, where values, usually the results of calculations, are stored in variables.
- Input / Output, data is read in or printed out.
- Control, the program makes a decision about what to do next.
This section will discuss the use of control statements in C. We will show how they can be used to write powerful programs by;
- Repeating important sections of the program.
- Selecting between optional sections of a program.
The if else Statement
This is used to decide whether to do something at a special point, or to decide between two courses of action.
The following test decides whether a student has passed an exam with a pass mark of 45
It is possible to use the if part without the else.
if (result >= 45)
printf("Pass\n");
else
printf("Fail\n");
Each version consists of a test, (this is the bracketed statement following the if). If the test is true then the next statement is obeyed. If is is false then the statement following the else is obeyed if present. After this, the rest of the program continues as normal.
if (temperature <>
If we wish to have more than one statement following the if or the else, they should be grouped together between curly brackets. Such a grouping is called a compound statement or a block.
Sometimes we wish to make a multi-way decision based on several conditions. The most general way of doing this is by using the else if variant on the if statement. This works by cascading several comparisons. As soon as one of these gives a true result, the following statement or block is executed, and no further comparisons are performed. In the following example we are awarding grades depending on the exam result.
if (result >= 45)
{ printf("Passed\n");
printf("Congratulations\n")
}
else
{ printf("Failed\n");
printf("Good luck in the resits\n");
}
In this example, all comparisons test a single variable called result. In other cases, each test may involve a different variable or some combination of tests. The same pattern can be used with more or fewer else if's, and the final lone else may be left out. It is up to the programmer to devise the correct structure for each programming problem.
if (result >= 75)
printf("Passed: Grade A\n");
else if (result >= 60)
printf("Passed: Grade B\n");
else if (result >= 45)
printf("Passed: Grade C\n");
else
printf("Failed\n");
The switch Statement
This is another form of the multi way decision. It is well structured, but can only be used in certain cases where;
- Only one variable is tested, all branches must depend on the value of that variable. The variable must be an integral type. (int, long, short or char).
- Each possible value of the variable can control a single branch. A final, catch all, default branch may optionally be used to trap all unspecified cases.
}
estimate(number)
int number;
/* Estimate a number as none, one, two, several, many */
{ switch(number) {
case 0 :
printf("None\n");
break;
case 1 :
printf("One\n");
break;
case 2 :
printf("Two\n");
break;
case 3 :
case 4 :
case 5 :
printf("Several\n");
break;
default :
printf("Many\n");
break;
}
Each interesting case is listed with a corresponding action. The break statement prevents any further statements from being executed by leaving the switch. Since case 3 and case 4 have no following break, they continue on allowing the same action for several values of number.
Both if and switch constructs allow the programmer to make a selection from a number of possible actions.
The other main type of control statement is the loop. Loops allow a statement, or block of statements, to be repeated. Computers are very good at repeating simple tasks many times, the loop is C's way of achieving this.
Loops
C gives you a choice of three types of loop, while, do while and for.
- The while loop keeps repeating an action until an associated test returns false. This is useful where the programmer does not know in advance how many times the loop will be traversed.
- The do while loops is similar, but the test occurs after the loop body is executed. This ensures that the loop body is run at least once.
- The for loop is frequently used, usually where the loop will be traversed a fixed number of times. It is very flexible, and novice programmers should take care not to abuse the power it offers.
The while Loop
The while loop repeats a statement until the test at the top proves false.
As an example, here is a function to return the length of a string. Remember that the string is represented as an array of characters terminated by a null character '\0'.
The string is passed to the function as an argument. The size of the array is not specified, the function will work for a string of any size.
int string_length(char string[])
{ int i = 0;
while (string[i] != '\0')
i++;
return(i);
}
The while loop is used to look at the characters in the string one at a time until the null character is found. Then the loop is exited and the index of the null is returned. While the character isn't null, the index is incremented and the test is repeated.
The do while Loop
This is very similar to the while loop except that the test occurs at the end of the loop body. This guarantees that the loop is executed at least once before continuing. Such a setup is frequently used where data is to be read. The test then verifies the data, and loops back to read again if it was unacceptable.
do
{ printf("Enter 1 for yes, 0 for no :");
scanf("%d", &input_value);
} while (input_value != 1 && input_value != 0)
The for Loop
The for loop works well where the number of iterations of the loop is known before the loop is entered. The head of the loop consists of three parts separated by semicolons.
- The first is run before the loop is entered. This is usually the initialisation of the loop variable.
- The second is a test, the loop is exited when this returns false.
- The third is a statement to be run every time the loop body is completed. This is usually an increment of the loop counter.
The break Statement
We have already met break in the discussion of the switch statement. It is used to exit from a loop or a switch, control passing to the first statement beyond the loop or a switch.
break;
With loops, break can be used to force an early exit from the loop, or to implement a loop with a test to exit in the middle of the loop body. A break within a loop should always be protected within an if statement which provides the test to control the exit condition.
The continue Statement
This is similar to break but is encountered less frequently. It only works within loops where its effect is to force an immediate jump to the loop control statement.
- In a while loop, jump to the test statement.
- In a do while loop, jump to the test statement.
- In a for loop, jump to the test, and perform the iteration.
The goto Statement
C has a goto statement which permits unstructured jumps to be made. Its use is not recommended, so we'll not teach it here. Consult your textbook for details of its use.
Input and Output
Input and output are covered in some detail. C allows quite precise control of these. This section discusses input and output from keyboard and screen.
The same mechanisms can be used to read or write data from and to files. It is also possible to treat character strings in a similar way, constructing or analysing them and storing results in variables. These variants of the basic input and output commands are discussed in the next section
The Standard Input Output File
UNIX supplies a standard package for performing input and output to files or the terminal. This contains most of the functions which will be introduced in this section, along with definitions of the datatypes required to use them. To use these facilities, your program must include these definitions by adding the line This is done by adding the line
#include
near the start of the program file. If you do not do this, the compiler may complain about undefined functions or datatypes.
Character Input / Output
This is the lowest level of input and output. It provides very precise control, but is usually too fiddly to be useful. Most computers perform buffering of input and output. This means that they'll not start reading any input until the return key is pressed, and they'll not print characters on the terminal until there is a whole line to be printed.
getchar
getchar returns the next character of keyboard input as an int. If there is an error then EOF (end of file) is returned instead. It is therefore usual to compare this value against EOF before using it. If the return value is stored in a char, it will never be equal to EOF, so error conditions will not be handled correctly.
As an example, here is a program to count the number of characters read until an EOF is encountered. EOF can be generated by typing Control - d.
#include
main()
{ int ch, i = 0;
while((ch = getchar()) != EOF)
i ++;
printf("%d\n", i);
}
putchar
putchar puts its character argument on the standard output (usually the screen).
The following example program converts any typed input into capital letters. To do this it applies the function toupper from the character conversion library ctype.h to each character in turn.
#include /* For definition of toupper */
#include /* For definition of getchar, putchar, EOF */
main()
{ int ch;
while((ch = getchar()) != EOF)
putchar(toupper(ch));
}
Formatted Input / Output
We have met these functions earlier in the course. They are closest to the facilities offered by Pascal or Fortran, and usually the easiest to use for input and output. The versions offered under C are a little more detailed, offering precise control of layout.
printf();
scanf();
Whole Lines of Input and Output
Where we are not too interested in the format of our data, or perhaps we cannot predict its format in advance, we can read and write whole lines as character strings. This approach allows us to read in a line of input, and then use various string handling functions to analyse it at our leisure.
gets();
puts();
C Programming - Pointers
declaration, Address operator, Pointer expressions & pointer arithmetic, Pointers and function, Call by value, Call by Reference, Pointer to arrays, Pointers and structures, Pointers on pointer.
Introduction:
In c a pointer is a variable that points to or references a memory location in which data is stored. Each memory cell in the computer has an address that can be used to access that location so a pointer variable points to a memory location we can access and change the contents of this memory location via the pointer.
Pointer declaration:
A pointer is a variable that contains the memory location of another variable. The syntax is as shown below. You start by specifying the type of data stored in the location identified by the pointer. The asterisk tells the compiler that you are creating a pointer variable. Finally you give the name of the variable.
type * variable name
Example:
int *ptr;
float *string;
Address operator:
Once we declare a pointer variable we must point it to something we can do this by assigning to the pointer the address of the variable you want to point as in the following example:
ptr=#
This places the address where num is stores into the variable ptr. If num is stored in memory 21260 address then the variable ptr has the value 21260.
/* A program to illustrate pointer declaration*/
main()
{
int *ptr;
int sum;
sum=45;
ptr=∑
printf (“\n Sum is %d\n”, sum);
printf (“\n The sum pointer is %d”, ptr);
}
we will get the same result by assigning the address of num to a regular(non pointer) variable. The benefit is that we can also refer to the pointer variable as *ptr the asterisk tells to the computer that we are not interested in the value 21260 but in the value stored in that memory location. While the value of pointer is 21260 the value of sum is 45 however we can assign a value to the pointer * ptr as in *ptr=45.
This means place the value 45 in the memory address pointer by the variable ptr. Since the pointer contains the address 21260 the value 45 is placed in that memory location. And since this is the location of the variable num the value also becomes 45. this shows how we can change the value of pointer directly using a pointer and the indirection pointer.
/* Program to display the contents of the variable their address using pointer variable*/
include<>
{
int num, *intptr;
float x, *floptr;
char ch, *cptr;
num=123;
x=12.34;
ch=’a’;
intptr=&x;
cptr=&ch;
floptr=&x;
printf(“Num %d stored at address %u\n”,*intptr,intptr);
printf(“Value %f stored at address %u\n”,*floptr,floptr);
printf(“Character %c stored at address %u\n”,*cptr,cptr);
}
Pointer expressions & pointer arithmetic:
Like other variables pointer variables can be used in expressions. For example if p1 and p2 are properly declared and initialized pointers, then the following statements are valid.
y=*p1**p2;
sum=sum+*p1;
z= 5* - *p2/p1;
*p2= *p2 + 10;
C allows us to add integers to or subtract integers from pointers as well as to subtract one pointer from the other. We can also use short hand operators with the pointers p1+=; sum+=*p2; etc.,
we can also compare pointers by using relational operators the expressions such as p1 >p2 , p1==p2 and p1!=p2 are allowed.
/*Program to illustrate the pointer expression and pointer arithmetic*/
#include<>
main()
{
int ptr1,ptr2;
int a,b,x,y,z;
a=30;b=6;
ptr1=&a;
ptr2=&b;
x=*ptr1+ *ptr2 –6;
y=6*- *ptr1/ *ptr2 +30;
printf(“\nAddress of a +%u”,ptr1);
printf(“\nAddress of b %u”,ptr2);
printf(“\na=%d, b=%d”,a,b);
printf(“\nx=%d,y=%d”,x,y);
ptr1=ptr1 + 70;
ptr2= ptr2;
printf(“\na=%d, b=%d”,a,b);
}
Pointers and function:
The pointer are very much used in a function declaration. Sometimes only with a pointer a complex function can be easily represented and success. The usage of the pointers in a function definition may be classified into two groups.
1. Call by reference
2. Call by value.
Call by value:
We have seen that a function is invoked there will be a link established between the formal and actual parameters. A temporary storage is created where the value of actual parameters is stored. The formal parameters picks up its value from storage area the mechanism of data transfer between actual and formal parameters allows the actual parameters mechanism of data transfer is referred as call by value. The corresponding formal parameter represents a local variable in the called function. The current value of corresponding actual parameter becomes the initial value of formal parameter. The value of formal parameter may be changed in the body of the actual parameter. The value of formal parameter may be changed in the body of the subprogram by assignment or input statements. This will not change the value of actual parameters.
/* Include<>
void main()
{
int x,y;
x=20;
y=30;
printf(“\n Value of a and b before function call =%d %d”,a,b);
fncn(x,y);
printf(“\n Value of a and b after function call =%d %d”,a,b);
}
fncn(p,q)
int p,q;
{
p=p+p;
q=q+q;
}
Call by Reference:
When we pass address to a function the parameters receiving the address should be pointers. The process of calling a function by using pointers to pass the address of the variable is known as call by reference. The function which is called by reference can change the values of the variable used in the call.
/* example of call by reference*?
/* Include<>
void main()
{
int x,y;
x=20;
y=30;
printf(“\n Value of a and b before function call =%d %d”,a,b);
fncn(&x,&y);
printf(“\n Value of a and b after function call =%d %d”,a,b);
}
fncn(p,q)
int p,q;
{
*p=*p+*p;
*q=*q+*q;
}
Pointer to arrays:
an array is actually very much like pointer. We can declare the arrays first element as a[0] or as int *a because a[0] is an address and *a is also an address the form of declaration is equivalent. The difference is pointer is a variable and can appear on the left of the assignment operator that is lvalue. The array name is constant and cannot appear as the left side of assignment operator.
/* A program to display the contents of array using pointer*/
main()
{
int a[100];
int i,j,n;
printf(“\nEnter the elements of the array\n”);
scanf(“%d”,&n);
printf(“Enter the array elements”);
for(I=0;I< ptr="a,ptr<">
Strings are characters arrays and here last element is \0 arrays and pointers to char arrays can be used to perform a number of string functions.
Pointers and structures:
We know the name of an array stands for the address of its zeroth element the same concept applies for names of arrays of structures. Suppose item is an array variable of struct type. Consider the following declaration:
struct products
{
char name[30];
int manufac;
float net;
item[2],*ptr;
this statement declares item as array of two elements, each type struct products and ptr as a pointer data objects of type struct products, the
assignment ptr=item;
would assign the address of zeroth element to product[0]. Its members can be accessed by using the following notation.
ptr- >name;
ptr- >manufac;
ptr- >net;
The symbol - > is called arrow pointer and is made up of minus sign and greater than sign. Note that ptr- > is simple another way of writing product[0].
When the pointer is incremented by one it is made to pint to next record ie item[1]. The following statement will print the values of members of all the elements of the product array.
for(ptr=item; ptr<>name,ptr- >manufac,ptr- >net);
We could also use the notation
(*ptr).number
to access the member number. The parenthesis around ptr are necessary because the member operator ‘.’ Has a higher precedence than the operator *.
Pointers on pointer:
While pointers provide enormous power and flexibility to the programmers, they may use cause manufactures if it not properly handled. Consider the following precaustions using pointers to prevent errors. We should make sure that we know where each pointer is pointing in a program. Here are some general observations and common errors that might be useful to remember.
A pointer contains garbage until it is initialized. Since compilers cannot detect uninitialized or wrongly initialized pointers, the errors may not be known until we execute the program remember that even if we are able to locate a wrong result, it may not provide any evidence for us to suspect problems in the pointers.
The abundance of c operators is another cause of confusion that leads to errors. For example the expressions such as
*ptr++, *p[],(ptr).member
etc should be carefully used. A proper understanding of the precedence and associativity rules should be carefully used.
C Programming - Structures and Unions
and Unions, Giving values to members, Initializing structure, Functions and structures, Passing structure to elements to functions, Passing entire function to functions, Arrays of structure, Structure within a structure and Union.
Arrays are used to store large set of data and manipulate them but the disadvantage is that all the elements stored in an array are to be of the same data type. If we need to use a collection of different data type items it is not possible using an array. When we require using a collection of different data items of different data types we can use a structure. Structure is a method of packing data of different types. A structure is a convenient method of handling a group of related data items of different data types.
structure definition:
general format:
struct tag_name
{
data type member1;
data type member2;
…
…
}
Example:
struct lib_books
{
char title[20];
char author[15];
int pages;
float price;
};
the keyword struct declares a structure to holds the details of four fields namely title, author pages and price. These are members of the structures. Each member may belong to different or same data type. The tag name can be used to define objects that have the tag names structure. The structure we just declared is not a variable by itself but a template for the structure.
We can declare structure variables using the tag name any where in the program. For example the statement,
struct lib_books book1,book2,book3;
declares book1,book2,book3 as variables of type struct lib_books each declaration has four elements of the structure lib_books. The complete structure declaration might look like this
struct lib_books
{
char title[20];
char author[15];
int pages;
float price;
};
struct lib_books, book1, book2, book3;
structures do not occupy any memory until it is associated with the structure variable such as book1. the template is terminated with a semicolon. While the entire declaration is considered as a statement, each member is declared independently for its name and type in a separate statement inside the template. The tag name such as lib_books can be used to declare structure variables of its data type later in the program.
We can also combine both template declaration and variables declaration in one statement, the declaration
struct lib_books
{
char title[20];
char author[15];
int pages;
float price;
} book1,book2,book3;
is valid. The use of tag name is optional for example
struct
{
…
…
…
}
book1, book2, book3 declares book1,book2,book3 as structure variables representing 3 books but does not include a tag name for use in the declaration.
A structure is usually defines before main along with macro definitions. In such cases the structure assumes global status and all the functions can access the structure.
Giving values to members:
As mentioned earlier the members themselves are not variables they should be linked to structure variables in order to make them meaningful members. The link between a member and a variable is established using the member operator ‘.’ Which is known as dot operator or period operator.
For example:
Book1.price
Is the variable representing the price of book1 and can be treated like any other ordinary variable. We can use scanf statement to assign values like
scanf(“%s”,book1.file);
scanf(“%d”,& book1.pages);
Or we can assign variables to the members of book1
strcpy(book1.title,”basic”);
strcpy(book1.author,”Balagurusamy”);
book1.pages=250;
book1.price=28.50;
/* Example program for using a structure*/
#include<>
void main()
{
int id_no;
char name[20];
char address[20];
char combination[3];
int age;
}newstudent;
printf(“Enter the student information”);
printf(“Now Enter the student id_no”);
scanf(“%d”,&newstudent.id_no);
printf(“Enter the name of the student”);
scanf(“%s”,&new student.name);
printf(“Enter the address of the student”);
scanf(“%s”,&new student.address);
printf(“Enter the cmbination of the student”);
scanf(“%d”,&new student.combination);
printf(“Enter the age of the student”);
scanf(“%d”,&new student.age);
printf(“Student information\n”);
printf(“student id_number=%d\n”,newstudent.id_no);
printf(“student name=%s\n”,newstudent.name);
printf(“student Address=%s\n”,newstudent.address);
printf(“students combination=%s\n”,newstudent.combination);
printf(“Age of student=%d\n”,newstudent.age);
}
Initializing structure:
Like other data type we can initialize structure when we declare them. As for initalization goes structure obeys the same set of rules as arrays we initalize the fields of a structure by the following structure declaration with a list containing values for weach fileds as with arrays these values must be evaluate at compile time.
Example:
Struct student newstudent
{
12345,
“kapildev”
“Pes college”;
“Cse”;
19;
};
this initializes the id_no field to 12345, the name field to “kapildev”, the address field to “pes college” the field combination to “cse” and the age field to 19.
Functions and structures:
We can pass structures as arguments to functions. Unlike array names however, which always point to the start of the array, structure names are not pointers. As a result, when we change structure parameter inside a function, we don’t effect its corresponding argument.
Passing structure to elements to functions:
A structure may be passed into a function as individual member or a separate variable.
A program example to display the contents of a structure passing the individual elements to a function is shown below.
# include <>
void main()
{
int emp_id;
char name[25];
char department[10];
float salary;
};
static struct emp1={125,”sampath”,”operator”,7500.00};
/* pass only emp_id and name to display function*/
display(emp1.emp_id,emp1.name);
}
/* function to display structure variables*/
display(e_no,e_name)
int e_no,e_name;
{
printf(“%d%s”,e_no,e_name);
in the declaration of structure type, emp_id and name have been declared as integer and character array. When we call the function display() using display(emp1.emp_id,emp1.name);
we are sending the emp_id and name to function display(0);
it can be immediately realized that to pass individual elements would become more tedious as the number of structure elements go on increasing a better way would be to pass the entire structure variable at a time.
Passing entire function to functions:
In case of structures having to having numerous structure elements passing these individual elements would be a tedious task. In such cases we may pass whole structure to a function as shown below:
# include stdio.h>
{
int emp_id;
char name[25];
char department[10];
float salary;
};
void main()
{
static struct employee emp1=
{
12,
“sadanand”,
“computer”,
7500.00
};
/*sending entire employee structure*/
display(emp1);
}
/*function to pass entire structure variable*/
display(empf)
struct employee empf
{
printf(“%d%s,%s,%f”, empf.empid,empf.name,empf.department,empf.salary);
}
Arrays of structure:
It is possible to define a array of structures for example if we are maintaining information of all the students in the college and if 100 students are studying in the college. We need to use an array than single variables. We can define an array of structures as shown in the following example:
structure information
{
int id_no;
char name[20];
char address[20];
char combination[3];
int age;
}
student[100];
An array of structures can be assigned initial values just as any other array can. Remember that each element is a structure that must be assigned corresponding initial values as illustrated below.
#include<>
{
struct info
{
int id_no;
char name[20];
char address[20];
char combination[3];
int age;
}
struct info std[100];
int I,n;
printf(“Enter the number of students”);
scanf(“%d”,&n);
printf(“ Enter Id_no,name address combination age\m”);
for(I=0;I < i="0;I<">
Structure within a structure:
A structure may be defined as a member of another structure. In such structures the declaration of the embedded structure must appear before the declarations of other structures.
struct date
{
int day;
int month;
int year;
};
struct student
{
int id_no;
char name[20];
char address[20];
char combination[3];
int age;
structure date def;
structure date doa;
}oldstudent, newstudent;
the sturucture student constains another structure date as its one of its members.
Union:
Unions like structure contain members whose individual data types may differ from one another. However the members that compose a union all share the same storage area within the computers memory where as each member within a structure is assigned its own unique storage area. Thus unions are used to observe memory. They are useful for application involving multiple members. Where values need not be assigned to all the members at any one time. Like structures union can be declared using the keyword union as follows:
union item
{
int m;
float p;
char c;
}
code;
this declares a variable code of type union item. The union contains three members each with a different data type. However we can use only one of them at a time. This is because if only one location is allocated for union variable irrespective of size. The compiler allocates a piece of storage that is large enough to access a union member we can use the same syntax that we use to access structure members. That is
code.m
code.p
code.c
are all valid member variables. During accessing we should make sure that we are accessing the member whose value is currently stored.
For example a statement such as
code.m=456;
code.p=456.78;
printf(“%d”,code.m);
Would prodece erroneous result.
In effect a union creates a storage location that can be used by one of its members at a time. When a different number is assigned a new value the new value supercedes the previous members value. Unions may be used in all places where a structure is allowed. The notation for accessing a union member that is nested inside a structure remains the same as for the nested structure.
C Programming - Functions
Functions are used in c for the following reasons, Function definition, Types of functions, Functions with no arguments and no return values, Functions with arguments but no return values, Functions with arguments and return values, Return value data type of function and Void functions.
The basic philosophy of function is divide and conquer by which a complicated tasks are successively divided into simpler and more manageable tasks which can be easily handled. A program can be divided into smaller subprograms that can be developed and tested successfully.
A function is a complete and independent program which is used (or invoked) by the main program or other subprograms. A subprogram receives values called arguments from a calling program, performs calculations and returns the results to the calling program.
There are many advantages in using functions in a program they are:
1. It facilitates top down modular programming. In this programming style, the high level logic of the overall problem is solved first while the details of each lower level functions is addressed later.
2. the length of the source program can be reduced by using functions at appropriate places. This factor is critical with microcomputers where memory space is limited.
3. It is easy to locate and isolate a faulty function for further investigation.
4. A function may be used by many other programs this means that a c programmer can build on what others have already done, instead of starting over from scratch.
5. A program can be used to avoid rewriting the same sequence of code at two or more locations in a program. This is especially useful if the code involved is long or complicated.
6. Programming teams does a large percentage of programming. If the program is divided into subprograms, each subprogram can be written by one or two team members of the team rather than having the whole team to work on the complex program
We already know that C support the use of library functions and use defined functions. The library functions are used to carry out a number of commonly used operations or calculations. The user-defined functions are written by the programmer to carry out various individual tasks.
Functions are used in c for the following reasons:
1. Many programs require that a specific function is repeated many times instead of writing the function code as many timers as it is required we can write it as a single function and access the same function again and again as many times as it is required.
2. We can avoid writing redundant program code of some instructions again and again.
3. Programs with using functions are compact & easy to understand.
4. Testing and correcting errors is easy because errors are localized and corrected.
5. We can understand the flow of program, and its code easily since the readability is enhanced while using the functions.
6. A single function written in a program can also be used in other programs also.
Function definition:
[ data type] function name (argument list)
argument declaration;
{
local variable declarations;
statements;
[return expression]
}
Example :
mul(a,b)
int a,b;
{
int y;
y=a+b;
return y;
}
When the value of y which is the addition of the values of a and b. the last two statements ie,
y=a+b; can be combined as
return(y)
return(a+b);
Types of functions:
A function may belong to any one of the following categories:
1. Functions with no arguments and no return values.
2. Functions with arguments and no return values.
3. Functions with arguments and return values.
Functions with no arguments and no return values:
Let us consider the following program
/* Program to illustrate a function with no argument and no return values*/
#include
main()
{
staetemtn1();
starline();
statement2();
starline();
}
/*function to print a message*/
statement1()
{
printf(“\n Sample subprogram output”);
}
statement2()
{
printf(“\n Sample subprogram output two”);
}
starline()
{
int a;
for (a=1;a<60;a++)>
In the above example there is no data transfer between the calling function and the called function. When a function has no arguments it does not receive any data from the calling function. Similarly when it does not return value the calling function does not receive any data from the called function. A function that does not return any value cannot be used in an expression it can be used only as independent statement.
Functions with arguments but no return values:
The nature of data communication between the calling function and the arguments to the called function and the called function does not return any values to the calling function this shown in example below:
Consider the following:
Function calls containing appropriate arguments. For example the function call
value (500,0.12,5)
Would send the values 500,0.12 and 5 to the function value (p, r, n) and assign values 500 to p, 0.12 to r and 5 to n. the values 500,0.12 and 5 are the actual arguments which become the values of the formal arguments inside the called function.
Both the arguments actual and formal should match in number type and order. The values of actual arguments are assigned to formal arguments on a one to one basis starting with the first argument as shown below:
main()
{
function1(a1,a2,a3……an)
}
function1(f1,f2,f3….fn);
{
function body;
}
here a1,a2,a3 are actual arguments and f1,f2,f3 are formal arguments.
The no of formal arguments and actual arguments must be matching to each other suppose if actual arguments are more than the formal arguments, the extra actual arguments are discarded. If the number of actual arguments are less than the formal arguments then the unmatched formal arguments are initialized to some garbage values. In both cases no error message will be generated.
The formal arguments may be valid variable names, the actual arguments may be variable names expressions or constants. The values used in actual arguments must be assigned values before the function call is made.
When a function call is made only a copy of the values actual arguments is passed to the called function. What occurs inside the functions will have no effect on the variables used in the actual argument list.
Let us consider the following program
/*Program to find the largest of two numbers using function*/
#include
main()
{
int a,b;
printf(“Enter the two numbers”);
scanf(“%d%d”,&a,&b);
largest(a,b)
}
/*Function to find the largest of two numbers*/
largest(int a, int b)
{
if(a>b)
printf(“Largest element=%d”,a);
else
printf(“Largest element=%d”,b);
}
in the above program we could make the calling function to read the data from the terminal and pass it on to the called function. But function foes not return any value.
Functions with arguments and return values:
The function of the type Arguments with return values will send arguments from the calling function to the called function and expects the result to be returned back from the called function back to the calling function.
To assure a high degree of portability between programs a function should generally be coded without involving any input output operations. For example different programs may require different output formats for displaying the results. Theses shortcomings can be overcome by handing over the result of a function to its calling function where the returned value can be used as required by the program. In the above type of function the following steps are carried out:
1. The function call transfers the controls along with copies of the values of the actual arguments of the particular function where the formal arguments are creates and assigned memory space and are given the values of the actual arguments.
2. The called function is executed line by line in normal fashion until the return statement is encountered. The return value is passed back to the function call is called function.
3. The calling statement is executed normally and return value is thus assigned to the calling function.
Note that the value return by any function when no format is specified is an integer.
Return value data type of function:
A C function returns a value of type int as the default data type when no other type is specified explicitly. For example if function does all the calculations by using float values and if the return statement such as return (sum); returns only the integer part of the sum. This is since we have not specified any return type for the sum. There is the necessity in some cases it is important to receive float or character or double data type. To enable a calling function to receive a non-integer value from a called function we can do the two things:
1. The explicit type specifier corresponding to the data type required must be mentioned in the function header. The general form of the function definition is
Type_specifier function_name(argument list)
Argument declaration;
{
function statement;
}
The type specifier tells the compiler, the type of data the function is to return.
2. The called function must be declared at the start of the body in the calling function, like any other variable. This is to tell the calling function the type of data the function is actually returning. The program given below illustrates the transfer of a floating-point value between functions done in a multiple function program.
main()
{
float x,y,add();
double sub(0;
x=12.345;
y=9.82;
printf(“%f\n” add(x,y));
printf(“%lf\n”sub(x,y);
}
float add(a,b)
float a,b;
{
return(a+b);
}
double sub(p,q)
double p,q;
{
return(p-q);
}
We can notice that the functions too are declared along with the variables. These declarations clarify to the compiler that the return type of the function add is float and sub is double.
Void functions:
The functions that do not return any values can be explicitly defined as void. This prevents any accidental use of these functions in expressions.
Example:
main()
{
void starline();
void message();
-------
}
void printline
{
statements;
}
void value
{
statements;
}
C Programming - Nesting of Functions
Nesting of functions, Recursion, Functions and arrays, The scope and lifetime of variables in functions, Automatic variables, External variables, Multi-file programs, Static variables and Register variables.
Nesting of functions:
C permits nesting of two functions freely. There is no limit how deeply functions can be nested. Suppose a function a can call function b and function b can call function c and so on. Consider the following program:
main()
{
int a,b,c;
float ratio();
scanf(“%d%d%d”,&a,&b,&c);
printf(“%f\n”,ratio(a,b,c));
}
float ratio(x,y,z)
int x,y,z;
{
if(difference(y,z))
return(x/y-z));
else
return(0,0);
}
difference(p,q)
{
int p,q;
{
if(p!=q)
return(1);
else
return(0);
}
the above program calculates the ratio a/b-c;
and prints the result. We have the following three functions:
main()
ratio()
difference()
main reads the value of a,b,c and calls the function ratio to calculate the value a/b-c) this ratio cannot be evaluated if(b-c) is zero. Therefore ratio calls another function difference to test whether the difference(b-c) is zero or not.
Recursion:
Recursive function is a function that calls itself. When a function calls another function and that second function calls the third function then this kind of a function is called nesting of functions. But a recursive function is the function that calls itself repeatedly.
A simple example:
main()
{
printf(“this is an example of recursive function”);
main();
}
when this program is executed. The line is printed reapeatedly and indefinitely. We might have to abruptly terminate the execution.
Functions and arrays:
We can pass an entire array of values into a function just as we pass indiviual variables. In this task it is essential to list the name of the array along with functions arguments without any subscripts and the size of the array as arguments
For example: The call
Largest(a,n);
Will pass all the elements contained in the array a of size n. the called function expecting this call must be appropriately defined. The largest function header might look like:
float smallest(array,size);
float array[];
int size;
The function smallest is defined to take two arguments, the name of the array and the size of the array to specify the number of elements in the array. The declaration of the formal argument array is made as follows:
float array[];
The above declaration indicates to compiler that the arguments array is an array of numbers. It is not necessary to declare size of the array here. While dealing with array arguments we should remember one major distinction. If a function changes the value the value of an array elements then these changes will be made to the original array that passed to the function. When the entire array is passed as an argument, the contents of the array are not copied into the formal parameter array instead information about the address of the array elements are passed on to the function. Therefore any changes introduced to array elements are truly reflected in the original array in the calling function.
The scope and lifetime of variables in functions:
The scope and lifetime of the variables define in C is not same when compared to other languages. The scope and lifetime depends on the storage class of the variable in c language the variables can be any one of the four storage classes:
1. Automatic Variables
2. External variable
3. Static variable
4. Register variable.
The scope actually determines over which part or parts of the program the variable is available. The lifetime of the variable retains a given value. During the execution of the program. Variables can also be categorized as local or global. Local variables are the variables that are declared within that function and are accessible to all the functions in a program and they can be declared within a function or outside the function also.
Automatic variables:
Automatic variables are declared inside a particular function and they are created when the function is called and destroyed when the function exits. Automatic variables are local or private to a function in which they are defined by default all variable declared without any storage specification is automatic. The values of variable remains unchanged to the changes that may happen in other functions in the same program and by doing this no error occurs.
/* A program to illustrate the working of auto variables*/
#include
void main()
{
int m=1000;
function2();
printf(“%d\n”,m);
}
function1()
{
int m=10;
printf(“%d\n”,m);
}
function2()
{
int m=100;
function1();
printf(“%d\n”,m);
}
A local variable lives through out the whole program although it accessible only in the main. A program with two subprograms function1 and function2 with m as automatic variable and is initialized to 10,100,1000 in function 1 function2 and function3 respectively. When executes main calls function2 which in turns calls function1. When main is active m=1000. But when function2 is called, the main m is temporarily put on the shelf and the new local m=100 becomes active. Similarly when function1 is called both previous values of m are put on shelf and latest value (m=10) become active, a soon as it is done main (m=1000) takes over. The output clearly shows that value assigned to m in one function does not affect its value in the other function. The local value of m is destroyed when it leaves a function.
External variables:
Variables which are common to all functions and accessible by all functions of aprogram are internal variables. External variables can be declared outside a function.
Example
int sum;
float percentage;
main()
{
…..
…..
}
function2()
{
….
….
}
The variables sum and percentage are available for use in all the three functions main, function1, function2. Local variables take precedence over global variables of the same name.
For example:
int i = 10;
void example(data)
int data;
{
int i = data;
}
main()
{
example(45);
}
In the above example both the global variable and local variable have the same name as i.
The local variable i take precedence over the global variable. Also the value that is stored in integer i is lost as soon as the function exits.
A global value can be used in any function all the functions in a program can access the global variable and change its value the subsequent functions get the new value of the global variable, it will be inconvenient to use a variable as global because of this factor every function can change the value of the variable on its own and it will be difficult to get back the original value of the variable if it is required.
Global variables are usually declared in the beginning of the main program ie., before the main program however c provides a facility to declare any variable as global this is possible by using the keyword storage class extern. Although a variable has been defined after many functions the external declaration of y inside the function informs the compiler that the variable y is integer type defined somewhere else in the program. The external declaration does not allocate storage space for the variables. In case of arrays the definition should include their size as well. When a variable is defined inside a function as extern it provides type information only for that function. If it has to be used in other functions then again it has to be re-declared in that function also.
Example:
main()
{
int n;
out_put();
extern float salary[];
……
…..
out_put();
}
void out_put()
{
extern float salary[];
int n;
….
…..
}
float salary[size];
a function when its parameters and function body are specified this tells the compiler to allocate space for the function code and provides type info for the parameters. Since functions are external by default we declare them (in calling functions) without the qualifier extern.
Multi-file programs:
Programs need not essentially be limited into a single file, multi-file programs is also possible, all the files are linked later to form executable object code. This approach is very useful since any change in one file does not affect other files thus eliminating the need for recompilation of the entire program. To share a single variable in multiple programs it should be declared, as external variables that are shared by two or more files are obviously global variables and therefore we must declare them accordingly in one file and explicitly define them with extern in other file. The example shown below illustrates the use of extern declarations in multi-file programs
File1.c
main()
{
extern int j;
int k;
}
function1()
{
int z;
…
….
}
file2.c
function2()
{
int k;
}
function3()
{
int num;
…
….
}
the function in main file1 reference the variable j that is declared as global in file 2. Here function1() cannot access j if the statement extern int k is places before main then both the functions could refer to j. this can also be achieved by using extern int j statement inside each function in file1.
The extern specifier tells the compiler that the following variables types and names have already been declared elsewhere and no need to create storage space for them. It is the responsibility of the linker to resolve the reference problem. It is important to note that a multi-file global variable should be declared without extern in one of the files.
Static variables:
The value given to a variable declared by using keyword static persistes until the end of the program.
A static variable is initialized only once, when the program is compiled. It is never initialized again. During the first call to stat in the example shown below x is incremented to 1. because x is static, this value persists and therefore the next call adds another 1 to x giving it a value of 2. The value of x becomes 3 when third call is made. If we had declared x as an auto then output would here been x=1 all the three times.
main()
{
int j;
for(j=1;j<3;j++)
stat();
}
stat();
{
static int x=0;
x=x+1;
printf(“x=%d\n”,x);
}
Register variables:
A variable is usually stored in the memory but it is also possible to store a varible in the compilers register by defining it as register variable. The registers access is much faster than a memory access, keeping the frequently accessed variables in the register will make the execution of the program faster.
This is done as follows:
register int count;
Since only a few variables can be placed in a register, it is important to carefully select the variables for this purpose. However c will automatically convert regisdter variables into normal variables once the limit is exceeded.
No comments:
Post a Comment