Pages

Subscribe:

Labels

Tuesday, 18 December 2012

Learn C Programming With Us


Watch Contents For More

Content



Storage Class In C


What is a Storage Class 

To fully define a variable one needs to mention not only its ‘type’ but also its ‘storage class’.
In other words, not only do all variables have a data type, they also have a ‘storage class’.

If we don’t specify the storage class of a variable in its declaration, the compiler will assume a storage class depending on the context in which the variable is used. Thus, variables have certain default storage classes.

There are basically two kinds of locations in a computer where such a value may be kept—
Memory and CPU registers.
It is the variable’s storage class that determines in which of these two locations the value is stored.

Moreover, a variable’s storage class tells us:

(a) Where the variable would be stored.

b) What will be the initial value of the variable, if initial value is
not specifically assigned.(i.e. the default initial value).

(c) What is the scope of the variable; i.e. in which functions the
value of the variable would be available.

(d) What is the life of the variable; i.e. how long would the
variable exist.

There are four storage classes in C:
(a) Automatic storage class
(b) Register storage class
(c) Static storage class
(d) External storage class

Let us examine these storage classes one by one.

Automatic Storage Class

The features of a variable defined to have an automatic storage class are as under:

->Storage − Memory.

->Default initial value − An unpredictable value, which is often called a garbage value.

->Scope − Local to the block in which the variable is defined.

->Life − Till the control remains within the block in which the variable is defined.

Following program shows how an automatic storage class variable is declared, and the fact that if the variable is not initialized it contains a garbage value.

main( )
{
auto int i, j ;
printf ( "\n%d %d", i, j ) ;
}

The output of the above program could be...

1211 221

where, 1211 and 221 are garbage values of i and j. When you run this program you may get different values, since garbage values are unpredictable. So always make it a point that you initialize the automatic variables properly, otherwise you are likely to get unexpected results. Note that the keyword for this storage class is auto, and not automatic.

Scope and life of an automatic variable is illustrated in the following program.

main( )
{
auto int i = 1 ;
{
{
{
printf ( "\n%d ", i ) ;
}
printf ( "%d ", i ) ;
}
printf ( "%d", i ) ;
}
}

The output of the above program is:

1 1 1

This is because, all printf( ) statements occur within the outermost block (a block is all statements enclosed within a pair of braces) in which i has been defined. It means the scope of i is local to the block in which it is defined.
The moment the control comes out of the block in which the variable is defined, the variable and its value is irretrievably lost.
To catch my point, go through the following program.

main( )
{
auto int i = 1 ;
{
auto int i = 2 ;
{
auto int i = 3 ;
printf ( "\n%d ", i ) ;
}
printf ( "%d ", i ) ;
}
printf ( "%d", i ) ;
}

The output of the above program would be:

3 2 1

Note that the Compiler treats the three i’s as totally different variables, since they are defined in different blocks.
Once the control comes out of the innermost block the variable i with value 3 is lost, and hence the i in the second printf( ) refers to i with value 2.
Similarly, when the control comes out of the next innermost block, the third printf( ) refers to the i with value 1.

Simple Example:
#include <stdio.h>
#include <conio.h>
void main()
{
auto int i=10;
clrscr();
{
auto int i=20;
printf("\n\t %d",i);
}
printf("\n\n\t %d",i);
getch();
}

Output :
20
10

Register Storage Class

The features of a variable defined to be of register storage class
are as under:

->Storage - CPU registers.

->Default initial value - Garbage value.

->Scope - Local to the block in which the variable is defined.

->Life - Till the control remains within the block in which the variable is defined.

A value stored in a CPU register can always be accessed faster than the one that is stored in memory. Therefore, if a variable is used at many places in a program it is better to declare its storage class as register. A good example of frequently used variables is loop counters.
We can name their storage class as register.

main( )
{
register int i ;
for ( i = 1 ; i <= 10 ; i++ )
printf ( "\n%d", i ) ;
}

Here, even though we have declared the storage class of i as register, we cannot say for sure that the value of i would be stored in a CPU register.
Why? Because the number of CPU registers are limited, and they may be busy doing some other task.
What happens in such an event... the variable works as if its storage class is auto.

Note :
This class is not applicable for arrays, structures or pointers.

It cannot not used with static or external storage class.

Unary and address of (&) cannot be used with these variables as explicitly or implicitly.

Static Storage Class

The features of a variable defined to have a static storage class are as under:

->Storage − Memory.

->Default initial value − Zero.

->Scope − Local to the block in which the variable is defined.

->Life − Value of the variable persists between different function calls.

Like auto variables, static variables are also local to the block in which they are declared.
The difference between them is that static variables don’t disappear when the function is no longer active. Their values persist. If the control comes back to the same function again the static variables have the same values they had last time around.

There are two types of static variables as :

a) Local Static Variable
b) Global Static Variable

Static storage class can be used only if we want the value of a variable to persist between different function calls.

Example :
#include <stdio.h>
#include <conio.h>

void main()
{
int i;
void incre(void);
clrscr();
for (i=0; i<3; i++)
incre();
getch();
}

void incre(void)
{
int avar=1;
static int svar=1;
avar++;
svar++;
printf("\n\n Automatic variable value : %d",avar);
printf("\t Static variable value : %d",svar);
}

Output :

Automatic variable value : 2 Static variable value : 2

Automatic variable value : 2 Static variable value : 3

Automatic variable value : 2 Static variable value : 4

External Storage Class

The features of a variable whose storage class has been defined as external are as follows:

->Storage − Memory.
->Default initial value − Zero.
->Scope − Global.
->Life − As long as the program’s execution doesn’t come to an end.

External variables are declared outside all functions, yet are available to all functions that care to use them.
Here is an example to illustrate this fact.

int i ;

main( )
{
printf ( "\ni = %d", i ) ;
increment( ) ;
increment( ) ;
decrement( ) ;
decrement( ) ;
}

increment( )
{
i = i + 1 ;
printf ( "\non incrementing i = %d", i ) ;
}

decrement( )
{
i = i - 1 ;
printf ( "\non decrementing i = %d", i ) ;
}

The output would be:

i = 0
on incrementing i = 1
on incrementing i = 2
on decrementing i = 1
on decrementing i = 0

As is obvious from the above output, the value of i is available to the functions increment( ) and decrement( ) since i has been declared outside all functions.

Look at the following program.

int x = 21 ;
main( )
{
extern int y ;
printf ( "\n%d %d", x, y ) ;
}
int y = 31 ;

Here, x and y both are global variables. Since both of them have been defined outside all the functions both enjoy external storage class.

Note the difference between the following:

extern int y ;
int y = 31 ;

Here the first statement is a declaration, whereas the second is the definition.
When we declare a variable no space is reserved for it, whereas, when we define it space gets reserved for it in memory.

Another small issue—what will be the output of the following program?

int x = 10 ;
main( )
{
int x = 20 ;
printf ( "\n%d", x ) ;

display( ) ;
}
display( )
{
printf ( "\n%d", x ) ;
}

Here x is defined at two places, once outside main( ) and once inside it. When the control reaches the printf( ) in main( ) which x gets printed?
Whenever such a conflict arises, it’s the local variable that gets preference over the global variable. Hence the printf( ) outputs 20.
When display( ) is called and control reaches the printf( ) there is no such conflict. Hence this time the value of the global x, i.e. 10 gets printed.

One last thing—a static variable can also be declared outside all the functions. For all practical purposes it will be treated as an extern variable.
However, the scope of this variable is limited to the same file in which it is declared.
This means that the variable would not be available to any function that is defined in a file other than the file in which the variable is defined.

Which to Use When

Dennis Ritchie has made available to the C programmer a number of storage classes with varying features, believing that the programmer is in a best position to decide which one of these storage classes is to be used when. We can make a few ground rules for usage of different storage classes in different programming situations with a view to:

(a) economise the memory space consumed by the variables
(b) improve the speed of execution of the program

The rules are as under:

− Use static storage class only if you want the value of a variable to persist between different function calls.

− Use register storage class for only those variables that are being used very often in a program. Reason is, there are very few CPU registers at our disposal and many of them might be busy doing something else. Make careful utilization of the scarce resources. A typical application of register storage class is loop counters, which get used a number of times in a program.

− Use extern storage class for only those variables that are being used by almost all the functions in the program. This would avoid unnecessary passing of these variables as arguments when making a function call. Declaring all the variables as extern would amount to a lot of wastage of memory space because these variables would remain active throughout the life of the program.

− If you don’t have any of the express needs mentioned above, then use the auto storage class. In fact most of the times we end up using the auto variables,
because often it so happens that once we have used the variables in a function we don’t mind loosing them.

Recursion in C



In C, it is possible for the functions to call themselves. A function is called ‘recursive’ if a statement within the body of a function calls the same function. Sometimes called ‘circular definition’, recursion is thus the process of defining something in terms of itself.

Let us now see a simple example of recursion. Suppose we want to calculate the factorial value of an integer.
As we know, the factorial of a number is the product of all the integers between 1 and that number.

For example, 4 factorial is 4 * 3 * 2 * 1. This can also be expressed as 4! = 4 * 3! where ‘!’ stands for factorial.
Thus factorial of a number can be expressed in the form of itself.
Hence this can be programmed using recursion.

Following is the recursive version of the function to calculate the
factorial value.

main( )
{
int a, fact ;
printf ( "\nEnter any number " ) ;
scanf ( "%d", &a ) ;
fact = rec ( a ) ;
printf ( "Factorial value = %d", fact ) ;
}
rec ( int x )
{
int f ;
if ( x == 1 )
return ( 1 ) ;
else
f = x * rec ( x - 1 ) ;
return ( f ) ;
}

And here is the output for four runs of the program

Enter any number 1
Factorial value = 1
Enter any number 2
Factorial value = 2
Enter any number 3
Factorial value = 6
Enter any number 5
Factorial value = 120


Description :

Let us understand this recursive factorial function thoroughly. In the first run when the number entered through scanf( ) is 1, let us see what action does rec( ) take. The value of a (i.e. 1) is copied into x.

Since x turns out to be 1 the condition if ( x == 1 ) is satisfied and hence 1 (which indeed is the value of 1 factorial) is returned through the return statement.

When the number entered through scanf( ) is 2, the ( x == 1 ) test fails, so we reach the statement,
f = x * rec ( x - 1 ) ;

And here is where we meet recursion. How do we handle the expression x * rec ( x - 1 )?
We multiply x by rec ( x - 1 ). Since the current value of x is 2, it is same as saying that
we must calculate the value (2 * rec ( 1 )).
We know that the value returned by rec ( 1 ) is 1, so the expression reduces to (2 * 1), or simply 2.

Thus the statement,
x * rec ( x - 1 ) ;

evaluates to 2, which is stored in the variable f, and is returned to main( ), where it is duly printed as Factorial value = 2

Now perhaps you can see what would happen if the value of a is 3, 4, 5 and so on.

In case the value of a is 5, main( ) would call rec( ) with 5 as its actual argument, and rec( ) will send back the computed value.
But before sending the computed value, rec( ) calls rec( ) and waits for a value to be returned.
It is possible for the rec( ) that has just been called to call yet another rec( ), the argument x being decreased in value by 1 for each of these recursive calls.

So we might say what happens is,

rec ( 5 ) returns ( 5 times rec ( 4 ),
which returns ( 4 times rec ( 3 ),
which returns ( 3 times rec ( 2 ),
which returns ( 2 times rec ( 1 ),
which returns ( 1 ) ) ) ) )

Call By Value Call By Reference


Two types of Function Calls

The two types of function calls are : call by value and call by reference.

Arguments can generally be passed to functions in one of the two ways:

(a) sending the values of the arguments

(b) sending the addresses of the arguments

Call by Value :

In the first method the ‘value’ of each of the actual arguments in the calling function is copied into corresponding formal arguments of the called function.
With this method the changes made to the formal arguments in the called function have no effect on the values of actual arguments in the calling function.

The following program illustrates the ‘Call by Value’.

main( )
{
int a = 10, b = 20 ;
swapv ( a, b ) ;
printf ( "\na = %d b = %d", a, b ) ;
}
swapv ( int x, int y )
{
int t ;
t = x ;
x = y ;
y = t ;
printf ( "\nx = %d y = %d", x, y ) ;
}

The output of the above program would be :

x = 20 y = 10
a = 10 b = 20

Note that values of a and b remain unchanged even after exchanging the values of x and y.

Call by Reference :

In this the addresses of actual arguments in the calling function are copied into formal
arguments of the called function.
This means that using these addresses we would have an access to the actual arguments and hence we would be able to manipulate them.

The following program illustrates this fact.

main( )
{
int a = 10, b = 20 ;
swapr ( &a, &b ) ;
printf ( "\na = %d b = %d", a, b ) ;
}
swapr( int *x, int *y )
{
int t ;
t = *x ;
*x = *y ;
*y = t ;
}

The output of the above program would be:
a = 20 b = 10

Note that this program manages to exchange the values of a and b using their addresses stored in x and y.

Usually in C programming we make a call by value. This means that in general you cannot alter the actual arguments.
But if desired, it can always be achieved through a call by reference.

Pointers in C


Introduction 

Which feature of C do beginners find most difficult to understand?
The answer is easy: pointers. Other languages have pointers but few use them so frequently as C does.
And why not? It is C’s clever use of pointers that makes it the excellent language it is.

Pointer notation :

Consider the declaration,

int i = 3 ;

This declaration tells the C compiler to:
(a) Reserve space in memory to hold the integer value.
(b) Associate the name i with this memory location.
(c) Store the value 3 at this location.

We may represent i’s location in memory by the following memory map.

i ----------------->location name
|-----------|
| 3-------- |------------>value at location
|-----------|
65524--------------->location number

Concept :

We see that the computer has selected memory location 65524 as the place to store the value 3. The location number 65524 is not a number to be relied upon, because some other time the computer may choose a different location for storing the value 3.
The important point is, i’s address in memory is a number.

We can print this address number through the following program:

main( )
{
int i = 3 ;
printf ( "\nAddress of i = %u", &i ) ;
printf ( "\nValue of i = %d", i ) ;
}

The output of the above program would be:
Address of i = 65524
Value of i = 3

Look at the first printf( ) statement carefully. ‘&’ used in this statement is C’s ‘address of’ operator.
The expression &i returns the address of the variable i, which in this case happens to be 65524. Since 65524 represents an address, there is no question of a sign being associated with it. Hence it is printed out using %u, which is a format specifier for printing an unsigned integer.
We have been using the ‘&’ operator all the time in the scanf( ) statement.
The other pointer operator available in C is ‘*’, called ‘value at address’ operator. It gives the value stored at a particular address.
The ‘value at address’ operator is also called ‘indirection’ operator.

Observe carefully the output of the following program:

main( )
{
int i = 3 ;
printf ( "\nAddress of i = %u", &i ) ;
printf ( "\nValue of i = %d", i ) ;
printf ( "\nValue of i = %d", *( &i ) ) ;
}

The output of the above program would be:

Address of i = 65524
Value of i = 3
Value of i = 3

Note that printing the value of *( &i ) is same as printing the value of i.
The expression &i gives the address of the variable i. This address can be collected in a variable, by saying,

j = &i ;

But remember that j is not an ordinary variable like any other integer variable.
It is a variable that contains the address of other variable (i in this case).
Since j is a variable the compiler must provide it space in the memory.
Once again, the following memory map would illustrate the contents of i and j.

i ----------------->location name
|-----------|
| 3-------- |------------>value at location
|-----------|
65524--------------->location number


j ----------------->location name
|-----------|
| 65522--|------------>value at location
|-----------|
65524--------------->location number



As you can see, i’s value is 3 and j’s value is i’s address.

But wait, we can’t use j in a program without declaring it. And since j is a variable that contains the address of i, it is declared as,
int *j ;

This declaration tells the compiler that j will be used to store the
address of an integer value. In other words j points to an integer.

How do we justify the usage of * in the declaration,
int *j ;

Let us go by the meaning of *. It stands for ‘value at address’.

Thus, int *j would mean, the value at the address contained in j is an int.

Here is a program that demonstrates the relationships we have been discussing.

main( )
{
int i = 3 ;
int *j ;
j = &i ;
printf ( "\nAddress of i = %u", &i ) ;
printf ( "\nAddress of i = %u", j ) ;
printf ( "\nAddress of j = %u", &j ) ;
printf ( "\nValue of j = %u", j ) ;
printf ( "\nValue of i = %d", i ) ;
printf ( "\nValue of i = %d", *( &i ) ) ;
printf ( "\nValue of i = %d", *j ) ;
}

The output of the above program would be:

Address of i = 65524
Address of i = 65524
Address of j = 65522
Value of j = 65524
Value of i = 3
Value of i = 3
Value of i = 3

Work through the above program carefully, taking help of the memory locations of i and j shown earlier. This program summarizes everything that we have discussed so far.

Look at the following declarations,

int *alpha ;
char *ch ;
float *s ;

Here, alpha, ch and s are declared as pointer variables,
i.e. variables capable of holding addresses. Remember that, addresses (location nos.) are always going to be whole numbers, therefore pointers always contain whole numbers.

Now we can put these two facts together and say—pointers are variables that contain
addresses, and since addresses are always whole numbers, pointers would always contain whole numbers. The declaration float *s does not mean that s is going to contain a floating-point value.

What it means is, s is going to contain the address of a floating-point value.
Similarly, char *ch means that ch is going to contain the address of a char value.
Or in other words, the value at address stored in ch is going to be a char.

The concept of pointers can be further extended. Pointer, we know is a variable that contains address of another variable.
Now this variable itself might be another pointer. Thus, we now have a pointer that contains another pointer’s address.
The following example should make this point clear.

main( )
{
int i = 3, *j, **k ;
j = &i ;
k = &j ;
printf ( "\nAddress of i = %u", &i ) ;
printf ( "\nAddress of i = %u", j ) ;
printf ( "\nAddress of i = %u", *k ) ;
printf ( "\nAddress of j = %u", &j ) ;
printf ( "\nAddress of j = %u", k ) ;
printf ( "\nAddress of k = %u", &k ) ;
printf ( "\nValue of j = %u", j ) ;
printf ( "\nValue of k = %u", k ) ;
printf ( "\nValue of i = %d", i ) ;
printf ( "\nValue of i = %d", * ( &i ) ) ;
printf ( "\nValue of i = %d", *j ) ;
printf ( "\nValue of i = %d", **k ) ;
}

The output of the above program would be:

Address of i = 65524
Address of i = 65524
Address of i = 65524
Address of j = 65522
Address of j = 65522
Address of k = 65520
Value of j = 65524
Value of k = 65522

Value of i = 3
Value of i = 3
Value of i = 3
Value of i = 3

The following Figure would help you in tracing out how the program prints the above output.

Remember that when you run this program the addresses that get printed might turn out to be something different than the ones shown in the figure.
However, with these addresses too the relationship between i, j and k can be easily established.

i ----------------->location name
|-----------|
| 3-------- |------------>value at location
|-----------|
65524--------------->location number

j ----------------->location name
|-----------|
| 65522--|------------>value at location
|-----------|
65524--------------->location number

k ----------------->location name
|-----------|
| 65520--|------------>value at location
|-----------|
65524--------------->location number


Observe how the variables j and k have been declared, int i, *j, **k ;

Here, i is an ordinary int, j is a pointer to an int (often called an integer pointer), whereas k is a pointer to an integer pointer.

Enumerated Data Type in C




The enumerated data type gives you an oppurtunity to invent your own data type and
define what values the variable of this data type can take.

This can help in making programs more readable, which can be an advantage when a
program gets complicated or when more than one programmer working on this.

Using enumerated datatype can help you to reduce the errors.

Syntax :

enum identifier{v1,v2,v3,.......vn};

or

enum identifier{v1,v2,v3,.......vn}variable;

As an example one could invent a data type called company_size which can have three
possible values-small,medium,large.

The format of enum definition is similar to that of structure.

Here's how the example stated above can be implemented :

enum company_size
{
small,medium,large
};
enum company_size company1,company2;

or we can also write it as :

enum company_size
{
small,medium,large
}
company1,company2;

Like structures this declaration has two parts :

(a) The first part daeclares the data type and specifies its possible values.
These values are called enumerators.

(b) The second part declares variables of this data type.

Now we can give values to these variables :

company1=small;
company2=medium;

One thing should be remember that we can't use values that aren't in the original
declaration.

Thus, the following expression would cause an error :

company1=very small; //error

Internally, the compiler treats the enumerators as integers. Each values of the enum
constants corresponds to an integer starting with 0.
Thus,in above example values are:

small =0;
medium=1;
large=2;

We can give explicit values like :

enum company_size
{
small=500,medium=1000,large=1500
};
enum company_size company1,company2;


Complete example :

#include <stdio.h>
#include <conio.h>

enum company_size
{
small=500,medium=1000,large=1500
};
enum company_size company1,company2;

void main()
{
company1=small;

printf("%d",company1);

getch();
}

Output :

500

Use :

Enumerated variables are usually used to clarify the operation of a program.
For example if we need to use comapny area/size in a program then we use enum
variables rather than declaring variables in main and assigning values them individually.
This will reduce the complexity of program and increase readibility.

Union in C


What is a Union

Union is user defined data type used to stored data under unique variable name at single memory location.

Union is similar to that of stucture. Syntax of union is similar to stucture.

If you know structures very well, then unions are similar to implement.

Main Difference between Union and Structure : 

The major difference between structure and union is 'storage.'

In structures, each member has its own storage location, whereas all the members of union use the same location.
Union contains many members of different types, it can handle only one member at a time.

Declaration of Union :

To declare union data type, 'union' keyword is used.

Union holds value for one data type which requires larger storage among their members.

Syntax:

union union_name
{
  element 1;
  element 2;
  element 3;
}union_variable;

Example:

union vee
{
 int comp_id;
 char nm;
 float sal;
}vi;

In above example, it declares 'vi' variable of type union. The union contains three members as data type of int, char, float. We can use only one of them at a time.

MEMORY ALLOCATION :

union-storage


     
 Fig : Memory allocation for union
To access union members, we can use the following syntax.

 vi.comp_id
vi.nm
vi.sal
That is dot operator is used as in case of structures.

Example :

#include <stdio.h>
#include <conio.h>
union vee
{
int id;
char nm[50];
}vi;


void main()
{
clrscr();
printf("\n\t Enter developer id : ");
scanf("%d", &vi.id);
printf("\n\n\t Enter developer name : ");
scanf("%s", vi.nm);
printf("\n\n Developer ID : %d", vi.id);//Garbage 
printf("\n\n Developed By : %s", vi.nm);
getch();
}

Output :

 Enter developer id : 101

 Enter developer name : technowell

        Developer ID : 25972

        Developed By : technowell

Structure in C


What is a Structure

Structure is user defined data type which is used to store heterogeneous data under unique name. Keyword 'struct' is used to declare structure.

The variables which are declared inside the structure are called as 'members of structure'.

Why Use Structures

We have seen earlier how ordinary variables can hold one piece of information and how arrays can hold a number of pieces of information of the same data type.
These two data types can handle a great variety of situations. But quite often we deal with entities that are collection of dissimilar data types.

For example, suppose you want to store data about a book. You might want to store its name (a string), its price (a float) and number of pages in it (an int).
If data about say 3 such books is to be stored, then we can follow two approaches:

(a)Construct individual arrays, one for storing names, another for storing prices and still another for storing number of pages.
(b)Use a structure variable.

The first approach become difficult and complex.

C provides a special data type—the structure.
A structure contains a number of data types grouped together. These data types may or may not be of the same type.

Syntax:

struct structure-name
{
element 1;
element 2;
- - - - - - - - - - -
- - - - - - - - - - -
element n;
}struct_variable;


Example :

struct emp_info
{
char emp_id[10];
char nm[100];
float sal;
}emp;

Note :
1. Structure is always terminated with semicolon (;).

2. Structure name as emp_info can be later used to declare structure variables of its type in a program.


INSTANCES OF STRUCTURE :
Instances of structure can be created in two ways as,

Instance 1:

struct emp_info
{
char emp_id[10];
char name[100];
float salary;
}emp;


Instance 2:

struct emp_info
{
char emp_id[10];
char name[100];
float salary;
};
struct emp_info emp;
In above example, emp_info is a simple structure which consists of stucture members as Employee ID(emp_id), Employee Name(nm), Employee Salary(sal).

ACEESSING STRUCTURE MEMBERS :
Structure members can be accessed using member operator '.' . It is also called as 'dot operator' or 'period operator'.

structure_var.member;

Example :

#include <stdio.h>
#include <conio.h>

struct comp_info
{
char name[100];
char addr[100];
}info;

void main()
{
clrscr();
printf("\n Enter Company Name : ");
gets(info.name);
printf("\n Enter Address : ");
gets(info.address);
printf("\n\n Company Name : %s",info.name);
printf("\n\n Address : %s",info.address);
getch();
}

Note : gets()function is used to enter the input. The advantage is that it takes the input with space character.

info.name---'dot' operator is used to access the name
info.address---'dot' operator is used to access the address

Output :

Enter Company Name : Software Solutions
Enter Address : Chandigarh

Company Name : Software Solutions
Address : Chandigarh


Array in Structures :

Sometimes, it is necessary to use structure members with array.


Example :

#include <stdio.h>
#include <conio.h>

struct result
{
int rno;
int mrks[5]; //array is used
char name;
}res;

void main()
{
int i,total;
clrscr();
total = 0;

printf("\n\t Enter Roll Number : ");
scanf("%d",&res.rno);

printf("\n\t Enter Marks of 3 Subjects : ");

for(i=0;i<3;i++)
{
scanf("%d",&res.mrks[i]); //array is used
total = total + res.mrks[i];
}

printf("\n\n\t Roll Number : %d",res.rno);
printf("\n\n\t Marks are :");

for(i=0;i<3;i++)
{
printf(" %d",res.mrks[i]);
}
printf("\n\n\t Total is : %d",total);
getch();
}

Output : 




??





Structures with array :

We can create structures with array for ease of operations in case of getting multiple same fields.

Example :


#include <stdio.h>
#include <conio.h>


struct result
{
int rno;
int mrks[5]; //array is used
char nm;
}res;

void main()
{
int i,total;
clrscr();
total = 0;

printf("\n\t Enter Roll Number : ");
scanf("%d",&res.rno);

printf("\n\t Enter Marks of 3 Subjects : ");

for(i=0;i<3;i++)
{
scanf("%d",&res.mrks[i]); //array is used
total = total + res.mrks[i];
}

printf("\n\n\t Roll Number : %d",res.rno);
printf("\n\n\t Marks are :");

for(i=0;i<3;i++)
{
printf(" %d",res.mrks[i]);
}
printf("\n\n\t Total is : %d",total);
getch();
}

Output :





??







Structure within a structure(Nesting of structure) :

Structures can be used as structures within structures. It is also called as 'nesting of structures'.


Syntax:

struct structure_nm
{
element 1;
element 2;
- - - - - - - - - - -
- - - - - - - - - - -
element n;

struct structure_nm
{
element 1;
element 2;
- - - - - - - - - - -
- - - - - - - - - - -
element n;
}inner_struct_var;
}outer_struct_var;


Example :

struct stud_Res
{
int rno;
char nm[50];
char std[10];

struct stud_subj
{
char subjnm[30];
int marks;
}subj;
}result;


In above example, the structure stud_Res consists of stud_subj which itself is a structure with two members. Structure stud_Res is called as 'outer structure' while stud_subj is called as 'inner structure.' The members which are inside the inner structure can be accessed as follow :

result.subj.subjnm
result.subj.marks

Example :

#include <stdio.h>
#include <conio.h>


struct stud_Res
{
int rno;
char std[10];
struct stud_Marks
{
char subj_nm[30];
int subj_mark;
}marks;
}result;

void main()
{
clrscr();
printf("\n\t Enter Roll Number : ");
scanf("%d",&result.rno);

printf("\n\t Enter Standard : ");
scanf("%s",result.std);

printf("\n\t Enter Subject Code : ");
scanf("%s",result.marks.subj_nm);

printf("\n\t Enter Marks : ");
scanf("%d",&result.marks.subj_mark);

printf("\n\n\t Roll Number : %d",result.rno);
printf("\n\n\t Standard : %s",result.std);
printf("\n\n\tSubject Code : %s",result.marks.subj_nm);
printf("\n\n\t Marks : %d",result.marks.subj_mark);

getch();
}

Output :




??











Summary :

(a)A structure is usually used when we wish to store dissimilar data together.

(b)Structure elements can be accessed through a structure variable using a dot (.)
operator.

(c)Structure elements can be accessed through a pointer to a structure using the
arrow (->) operator.

(d)All elements of one structure variable can be assigned to another structure variable using
the assignment (=) operator.

(e)It is possible to pass a structure variable to a function either by value or by address.

(f)It is possible to create an array of structures.

Array In C


What is an Array

An array is a collection of similar elements. These similar elements could be all ints, or all floats, or all chars, etc.

For understanding the arrays properly, let us consider the following program:

main( )
{
int x ;
x = 5 ;
x = 10 ;
printf ( "\nx = %d", x ) ;
}

No doubt, this program will print the value of x as 10. Why so? Because when a value 10 is assigned to x, the earlier value of x, i.e. 5, is lost. Thus, ordinary variables (the ones which we have used so far) are capable of holding only one value at a time (as in the above example). However, there are situations in which we would want to store more than one value at a time in a single variable.
For example, suppose we wish to arrange the percentage marks obtained by 100 students in ascending order. In such a case we have two options to store these marks in memory:

(a) Construct 100 variables to store percentage marks obtained by 100 different students, i.e. each variable containing one student’s marks.
(b)Construct one variable (called array or subscripted variable) capable of storing or holding all the hundred values.

Obviously, the second alternative is better. A simple reason for this is, it would be much easier to handle one variable than handling 100 different variables.

Moreover, there are certain logics that cannot be dealt with, without the use of an array. Now a formal definition of an array—An array is a collective name given to a group of ‘similar quantities’. These similar quantities could be percentage marks of 100 students, or salaries of 300 employees, or ages of 50 employees. What is important is that the quantities must be ‘similar’. Each member in the group is referred to by its position in the group. For example, assume the following group of numbers, which represent percentage marks obtained by five students.

per = { 48, 88, 34, 23, 96 }

If we want to refer to the second number of the group, the usual notation used is per[2] which have value 88. Similarly per[0] will denote the first element that is 48.This is because in C the counting of elements begins with 0 and not with 1.

A Simple Program Using Array

Let us try to write a program to find average marks obtained by a
class of 30 students in a test.

main( )
{
int avg, sum = 0 ;
int i ;
int marks[30] ; /* array declaration */
for ( i = 0 ; i <= 29 ; i++ )
{
printf ( "\nEnter marks " ) ;
scanf ( "%d", &marks[i] ) ; /* store data in array */
}
for ( i = 0 ; i <= 29 ; i++ )
sum = sum + marks[i] ; /* read data from an array*/
avg = sum / 30 ;
printf ( "\nAverage marks = %d", avg ) ;
}

There is a lot of new material in this program, so let us take it apart
slowly.

Array Declaration

To begin with, like other variables an array needs to be declared so that the compiler will know what kind of an array and how large an array we want. In our program we have done this with the statement:

int marks[30] ;

Here, int specifies the type of the variable, just as it does with ordinary variables and the word marks specifies the name of the variable.
The number 30 tells how many elements of the type int will be in our array. This number is often called the ‘dimension’ of the array.
The bracket ( [ ] ) tells the compiler that we are dealing with an array.
All the array elements are numbered, starting with 0. Thus, marks[2] is not the second element of the array, but the third.
In our program we are using the variable i as a subscript to refer to various elements of the array. This variable can take different values and hence can refer to the different elements in the array in turn. This ability to use variables as subscripts is what makes arrays so useful.

Entering Data into an Array

Here is the section of code that places data into an array:

for ( i = 0 ; i <= 29 ; i++ )
{
printf ( "\nEnter marks " ) ;
scanf ( "%d", &marks[i] ) ;
}

The for loop causes the process of asking for and receiving a student’s marks from the user to be repeated 30 times.

The first time through the loop, i has a value 0, so the scanf( ) function will cause the value typed to be stored in the array element marks[0], the first element of the array. This process will be repeated until ibecomes 29. This is last time through the loop, which is a good thing, because there is no array element like marks[30].

In scanf( ) function, we have used the “address of” operator (&) on the element marks[i] of the array, just as we have used it earlier on other variables (&rate, for example).
In so doing, we are passing the address of this particular array element to the scanf( ) function, rather than its value; which is what scanf( ) requires.

Reading Data from an Array

The balance of the program reads the data back out of the array and uses it to calculate the average. The for loop is much the same, but now the body of the loop causes each student’s marks to be added to a running total stored in a variable called sum. When all the marks have been added up, the result is divided by 30, the number of students, to get the average.

for ( i = 0 ; i <= 29 ; i++ )
sum = sum + marks[i] ;
avg = sum / 30 ;
printf ( "\nAverage marks = %d", avg ) ;

To fix our ideas, let us revise whatever we have learnt about arrays:

(a)An array is a collection of similar elements.
(b)The first element in the array is numbered 0, so the last element is 1 less than the size of the array.
(c)An array is also known as a subscripted variable.
(d)Before using an array its type and dimension must be
declared.

Types of Array

An array is of two types :
One/Single dimensional array
Two dimensional array
One/Single dimensional array

The array which is used to represent and store data in a linear form is called as 'single or one dimensional array.'

Syntax:

  [size];

Example:

int a[3] = {2, 3, 5};
char ch[20] = "Ashish" ;
float stax[3] = {5003.23, 1940.32, 123.20} ;

Total Size (in Bytes):

total size = length of array * size of data type

In above example, a is an array of type integer which has storage size of 3 elements. The total size would be 3 * 2 = 6 bytes.

MEMORY ALLOCATION :

single-d-array
     
Fig : Memory allocation for one dimensional array

Example :
#include <stdio.h>
#include <conio.h>

void main()
{
int a[3], i;;
clrscr();

printf("\n\t Enter three numbers : ");

for(i=0; i<3; i++)
{
scanf("%d", &a[i]); // read array
}

printf("\n\n\t Numbers are : ");

for(i=0; i<3; i++)
{
printf("\t %d", a[i]); // print array
}
getch();
}

Output :


Enter three numbers : 

Numbers are : 1     2     3





Two dimensional array

So far we have explored arrays with only one dimension. It is also possible for arrays to have two or more dimensions. The twodimensional array is also called a matrix. Here is a sample program that stores roll number and marks obtained by a student side by side in a matrix.

main( )
{
int stud[4][2] ;

int i, j ;

for ( i = 0 ; i <= 3 ; i++ )
{
printf ( "\n Enter roll no. and marks" ) ;
scanf ( "%d %d", &stud[i][0], &stud[i][1] ) ;
}

for ( i = 0 ; i <= 3 ; i++ )
printf ( "\n%d %d", stud[i][0], stud[i][1] ) ;
}

There are two parts to the program—in the first part through a for loop we read in the values of roll no. and marks, whereas, in second part through another for loop we print out these values.
Look at the scanf( ) statement used in the first for loop:

scanf ( "%d %d", &stud[i][0], &stud[i][1] ) ;

In stud[i][0] and stud[i][1] the first subscript of the variable stud, is row number which changes for every student. The second subscript tells which of the two columns are we talking about—
the zeroth column which contains the roll no. or the first column which contains the marks. Remember the counting of rows and columns begin with zero. The complete array arrangement is shown below.

col. no. 0 col. no. 1
row no. 0 1234 56
row no. 1 1212 33
row no. 2 1434 80
row no. 3 1312 78


Thus, 1234 is stored in stud[0][0], 56 is stored in stud[0][1] and so on. The above arrangement highlights the fact that a two dimensional array is nothing but a collection of a number of one dimensional arrays placed one below the other.
In our sample program the array elements have been stored rowwise and accessed rowwise. However, you can access the array elements columnwise as well.

The following syntax is used to represent two dimensional array.


Syntax:

[row_subscript][column-subscript];

Example:

#include <stdio.h>
#include <conio.h>

void main()
{
int a[3][3], i, j;
clrscr();
printf("\n\t Enter matrix of 3*3 : ");
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
{
scanf("%d",&a[i][j]); //read 3*3 array
}
}
printf("\n\t Matrix is : \n");
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
{
printf("\t %d",a[i][j]); //print 3*3 array
}
printf("\n");
}
getch();
}

Output :

Enter matrix of 3*3 : 1,2,3,4,5,6,7,8,9
 1       2        3
 4       5        6
 7       8        9








Limitations of two dimensional array :

We cannot delete any element from an array.
If we dont know that how many elements have to be stored in a memory in advance, then there will be memory wastage if large array size is specified.
Summary

(a)An array is similar to an ordinary variable except that it can store multiple elements of similar type.

(b)Compiler doesn’t perform bounds checking on an array.

(c)The array variable acts as a pointer to the zeroth element of the array.
In a 1-D array, zeroth element is a single value, whereas, in a 2-D array this element is a 1-D array.

(d)On incrementing a pointer it points to the next location of its type.

(e)Array elements are stored in contiguous memory locations and so they can be accessed using pointers.

Functions in C


What is a Function

A function is a self-contained block of statements that perform a coherent task of some kind.
Every C program can be thought of as a collection of these functions.

Note: Every identifier which has () that is paranthesis is a function for eg main() is a function.

Let us now look at a simple C function that operates in much the same way as the mechanic. Actually, we will be looking at two things—a function that calls or activates the function and the function itself.

main( ) //main function
{
void message( ) ; //function declaration or prototype

message(); //function call

printf ( "\nWelcome to functions" ) ;
}

void message( ) //function definition
{
printf ( "\nWelcome" ) ;
}

And here’s the output...
Welcom
Welcome to functions

Here, main( ) itself is a function and through it we are calling the function message( ).
What do we mean when we say that main( ) ‘calls’ the function message( )?
We mean that the control passes to the function message( ). The activity of main( ) is temporarily suspended; it falls asleep while the message( ) function wakes up and goes to work. When the message( ) function runs out of statements to execute, the control returns to main( ), which comes to life again and begins executing its code at the exact point where it left off. Thus, main( ) becomes the ‘calling’ function, whereas message( ) becomes the ‘called’ function.

If you have grasped the concept of ‘calling’ a function you are prepared for a call to more than one function. Consider the following example:

main( )
{
void italy( ) ;
void brazil( ) ;
void argentina( ) ;

printf ( "\nI am in main" ) ;
italy( ) ;
brazil( ) ;
argentina( ) ;
}

void italy( )
{
printf ( "\nI am in italy" ) ;
}
void brazil( )
{
printf ( "\nI am in brazil" ) ;
}
void argentina( )
{
printf ( "\nI am in argentina" ) ;
}

The output of the above program when executed would be as under:

I am in main
I am in italy
I am in brazil
I am in argentina

From this program a number of conclusions can be drawn:

− Any C program contains at least one function.

− If a program contains only one function, it must be main( ).

− If a C program contains more than one function, then one (and
only one) of these functions must be main( ), because program
execution always begins with main( ).

− There is no limit on the number of functions that might be
present in a C program.

− Each function in a program is called in the sequence specified
by the function calls in main( ).

− After each function has done its thing, control returns to
main( ).When main( ) runs out of function calls, the program
ends.

A Function has three parts :

  • Function declaration or function prototype
  • Function call
  • Function definition

Function declaration or prototype :

It specifies the name of the function, its return type and its arguments. It should be before the main method or inside the main method. For example void message();

Note: It should end with a ';' (semicolon);

Function call :

Function call is done by the calling function to invoke that function. When function call is made then the control is transffered to the function definition. It should be in a method which act as calling method.

Function Definition :

It consists of function body that is the respective statements which execute when the function is invoked.
For eg: void message()

Note: 
The return type and the arguments should be the same as specified in function declaration or prototype . For eg: message has void return type and no argument as we specified in function declaration.
Function definition should not end with ';'(semicolon)

Syntax:

void main()
{
// Function prototype
([]);

// Function Call
([]);
}
// Function definition
([]);
{
;
}


Types of functions :

There are two types of functions :

  1. Built in functions
  2. User defined functions


1. Built in functions

These functions are also called as 'library functions'. These functions are provided by system. These functions are stored in library files. e.g.

  • scanf()
  • printf()
  • getch()
  • getche()
  • clrscr();
  • gotoxy(int x,int y);
  • strlen
  • strcat
  • We had already discussed some of these in the
  • Some in-built functions tutorial section

click on the above link to go to this section.

2. User defined functions

The functions which are created by user for program are known as 'User defined functions'.
As for example :

main( )
{
void italy( ) ;
void brazil( ) ;
void argentina( ) ;

printf ( "\nI am in main" ) ;

italy( ) ;
brazil( ) ;
argentina( ) ;
}

void italy( )
{
printf ( "\nI am in italy" ) ;
}
void brazil( )
{
printf ( "\nI am in brazil" ) ;
}
void argentina( )
{
printf ( "\nI am in argentina" ) ;
}

Here we have created 3 user-defined functions-
italy(), brazil() and argentina

Note that the calling function that is main() is a built-in function.

Function declaration and Prototypes :
Any C function by default returns an int value. More specifically, whenever a call is made to a function, the compiler assumes that this function would return a value of the type int. If we desire that a function should return a value other than an int, then it is necessary to explicitly mention so in the calling function as well as in the called function. Suppose we want to find out square of a number using a function. This is how this simple program would look like:

main( )
{
float a, b ;
printf ( "\nEnter any number " ) ;
scanf ( "%f", &a ) ;
b = square ( a ) ;
printf ( "\nSquare of %f is %f", a, b ) ;
}

square ( float x )
{
float y ;
y = x * x ;
return ( y ) ;
}

And here are two sample runs of this program...

Enter any number 3
Square of 3 is 9.000000
Enter any number 1.5
Square of 1.5 is 2.000000

The first of these answers is correct. But square of 1.5 is definitely not 2.This happened because any C function, by default, always returns an integer value. Therefore, even though the function square( ) calculates the square of 1.5 as 2.25, the problem crops up when this 2.25 is to be returned to main( ). square( ) is not capable of returning a float value. How do we overcome this?

The following program segment illustrates how to make square( ) capable of returning a float value.

main( )
{
float square ( float ) ;
float a, b ;
printf ( "\nEnter any number " ) ;
scanf ( "%f", &a ) ;
b = square ( a ) ;
printf ( "\nSquare of %f is %f", a, b ) ;
}

float square ( float x )
{
float y ;
y = x * x ;
return ( y ) ;
}

And here is the output...
Enter any number 1.5
Square of 1.5 is 2.250000
Enter any number 2.5
Square of 2.5 is 6.250000

Now the expected answers i.e. 2.25 and 6.25 are obtained. Note that the function square( ) must be declared in main( ) as float square ( float ) ;
This statement is often called the prototype declaration of the square( ) function. What it means is square( ) is a function that receives a float and returns a float.

  • Function with no return type and no argument.
  • Function with return type and no arguments.
  • Function with return type and with argument.
  • Function with no return type and with argument.
  • Functions with no return type and no argument


In this the function has not any arguments and it doesn't return any type, means its type is void
since void means empty.

For eg:

void main()- this is the in-built method having no return type and no argument.

Program in which we have user defined function:

#include <stdio.h>
#include <conio.h>

void main()
{
void message();

clrscr();

message();

getch();


}

void message()
{
printf("Functions");
}

Output:


Functions

Function with return type and no arguments

In this the function returns a type but does not contain any arguments.

Example:

#include <stdio.h>
#include <conio.h>

void main()
{
int value();

int a=value();

clrscr();

printf("value of a is : %d",a);

getch();


}

int value()
{
int x=10;
return x;
}

Output:

Value of a is : 10

Function with return type and with argument

This type of functions have return type along with the arguments.

Example:

#include <stdio.h>
#include <conio.h>

void main()
{
int sum(int,int); // function having return type and consist of two integer type arguments

int x=10;
int y=10;

int result=sum(x,y);

clrscr();

printf("Sum is : %d",result);

getch();


}

int sum(int a,int b)
{
int sum=0;
sum=a+b;
return sum;
}

Output :

Sum is : 20

Note :
int sum(int,int); that is the function declaration can be before the start of main function.
So following program is also correct :-


#include <stdio.h>
#include <conio.h>

int sum(int,int); //declaration is before main() function

void main()
{
int x=10;
int y=10;

int result=sum(x,y);

clrscr();

printf("Sum is : %d",result);

getch();


}

int sum(int a,int b)
{
int sum=0;
sum=a+b;
return sum;
}

Output :

Sum is : 20

Function with no return type and with argument

In this the function has arguments but doesn't have any return type.

Example :

#include <stdio.h>
#include <conio.h>

void main()
{
void sum(int,int); // function consist of two integer type arguments but not have return type

int x=10;
int y=10;

sum(x,y);

clrscr();
}

void sum(int a,int b)
{
int sum=0;
sum=a+b;
printf("Sum is : %d",sum);
getch();
}


Output :

Sum is : 20

Advantages of functions :


  • It is easy to use.
  • Debugging is more suitable for programs.
  • It reduces the size of a program.
  • It is easy to understand the actual logic of a program.
  • Highly suited in case of large programs.
  • By using functions in a program, it is possible to construct modular and structured programs.


C Continue Statement




In some programming situations we want to take the control to the beginning of the loop, bypassing the statements inside the loop, which have not yet been executed.
The keyword continue allows us to do this. When continue is encountered inside any loop, control automatically passes to the beginning of the loop.

The working structure of 'continue' is similar as that of that break statement but difference is that it cannot terminate the loop. It causes the loop to be continued with next iteration after skipping statements in between. Continue statement simply skipps statements and continues next iteration.


Syntax :

continue;


Example :

#include <stdio.h>
#include <conio.h>

void main()
{
int i;
clrscr();
for<(i=1; i<=5; i++)
{
if(i==3) continue;
printf("\n\t %d",i); // 3 is omitted
}
getch();
}

Output :

1
2
3
4
5

Description :

The for loop executes normaly from i=1 to i=5, and display the respective values as output ,but when the value of i become 3, the continue statement executes which omit the printing of the value i=3.

Break statement in C



We often come across situations where we want to jump out of a loop instantly, without waiting to get back to the conditional test. The keyword break allows us to do this. When break is encountered inside any loop, control automatically passes to the first statement after the loop.
A break is usually associated with an if.

Simple Example :

#include <stdio.h>
#include <conio.h>

void main()
{
int i;
clrscr();

for(i=1;i<=7;i++)
{

if(i==3)
break;

printf("\n%d",i);
}
getch();
}

Output :

1
2

Description :

The for loop execute from i=1, since the condition is true hence its value is printed this
is continued for i=2 and again printing its value.But wheni=3 then if condition is true and
the break statement executes terminating the control from the loop.

Another Example:

This example is already explained in the Switch case section.

#include <stdio.h>
#include <conio.h>

void main()
{
int no;
clrscr();
printf("\n Enter any number from 1 to 3 :");
scanf("%d",&no);
switch(no)
{
case 1:
printf("\n\n It is 1 !");
break;
case 2:
printf("\n\n It is 2 !");
break;
case 3:
printf("\n\n It is 3 !");
break;
default:
printf("\n\n Invalid number !");
}
getch();
}