UNIT 5
STRUCTURE AND POINTERS
Structure
A structure can be considered as a template used for defining a collection of variables under a single name. Structures help programmers to group elements of different data types into a single logical unit (Unlike arrays which permit a programmer to group only elements of same data type).
- Why Use Structures
• Ordinary variables can hold one piece of information
• arrays can hold a number of pieces of information of the same data type.
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:
- Construct individual arrays, one for storing names, another for storing prices and still another for storing number of pages.
- Use a structure variable.
Suppose we want to create a employee database. Then, we can define a structure
calledemployee with three elements id, name and salary. The syntax of this structure is as
follows:
struct employee { int id; char name[50]; float salary; }; |
Note:
- Struct keyword is used to declare structure.
- Members of structure are enclosed within opening and closing braces.
- Usually structure type declaration appears at the top of the source code file, before any variables or functions are defined or maintained in separate header file.
- Declaration of Structure reserves no space.
- It is nothing but the “ Template / Map / Shape ” of the structure .
- Memory is created , very first time when the variable is created / Instance is created.
- Structure variable declaration:
We can declare the variable of structure in two ways
- Declare the structure inside main function
- Declare the structure outside the main function.
1. Declare the structure inside main function
Following example show you, how structure variable is declared inside main function
struct employee { int id; char name[50]; float salary; }; int main() { struct employee e1, e2; return 0; } |
In this example the variable of structure employee is created inside main function that e1 ,e2.
2. Declare the structure outside main function
Following example show you, how structure variable is declared outside the main function
struct employee { int id; char name[50]; float salary; }e1,e2; |
- Memory allocation for structure
Memory is allocated to the structure only when we create the variable of structure.
Consider following example
|
- Structure Initialization
1. When we declare a structure, memory is not allocated for un-initialized variable.
2. Let us discuss very familiar example of structure student , we can initialize structure variable
in different ways –
Way 1 : Declare and Initialize
Struct student { char name[20]; int roll; float marks; }std1 = { "Poonam",89,78.3 }; In the above code snippet, we have seen that structure is declared and as soon as after declaration we have initialized the structure variable. std1 = { "Poonam",89,78.3 } |
This is the code for initializing structure variable in C programming
Way 2 : Declaring and Initializing Multiple Variables
struct student
{
char name[20]; int roll; float marks; } std1 = {"Poonam" ,67, 78.3}; std2 = {"Vishal",62, 71.3}; In this example, we have declared two structure variables in above code. After declaration of variable we have initialized two variable. std1 = {"Poonam" ,67, 78.3}; std2 = {"Vishal",62, 71.3}; |
Way 3 : Initializing Single member struct student { int mark1; int mark2; int mark3; } sub1={67}; Though there are three members of structure,only one is initialized , Then remaining two members are initialized with Zero. If there are variables of other data type then their initial |
values will be –
Data Type Default value if not initialized
integer 0
float 0.00
char NULL
Way 4 : Initializing inside main
struct student
{ int mark1; int mark2; int mark3; }; void main() { struct student s1 = {89,54,65}; - - - - -- - - - - -- - - - - -- }; When we declare a structure then memory won’t be allocated for the structure. i.e only writing below declaration statement will never allocate memory struct student { int mark1; int mark2; int mark3; }; We need to initialize structure variable to allocate some memory to the structure. struct student s1 = {89,54,65}; Pointers The pointer in C language is a variable which stores the address of another variable. This variable can be of type int, char, array, function, or any other pointer. ... int n = 10; int* p = &n; // Variable p of type pointer is pointing to the address of the variable n of type integer. |
One of the vital and heavily used feature ‘C’ is pointer. Most of the other programming languages also support pointers but only few of them use it freely. Support pointers but only few of them use it freely.
When we declare any variable in C language, there are three things associated with that variable.
1. Data type of variable : Data type defines the type of data that variable can hold. Data type tells compiler about the amount of memory allocate to the variable.
2. Address of Variable : Address of variable represent the exact address of memory location which is allocated to variable.
3. Value of variable : It is the value of variable which is store at the address of memory location allocated to variable.
Example :int n = 5;
In the above example ‘int’ is the data type which tells compiler to allocate 2 bytes of memory to variable ‘n’.
Once the variable is declare compiler allocated two bytes of memory to variable ‘n’. Suppose the address of that memory location is 1020. At the address of memory location 1020 the value 5 is store.
Memory map for above declaration is as follows.
use of &,/and ‘*’ operator
Consider the following program.
#include<stdio.h>
#include<conio.h>
void main()
{
inta,b,c,
printf (“Enter two numbers”);
scanf (“%d%d”, &a,&b);
c=a+b;
printf(“/n Addition is %d”, C);
printf(“/n Address of variable C is %d”, &C);
getch ();
}
Above program is the program for addition of two numbers in ‘C’ language. In the sevent instruction of above program we used operator ‘%’ and ‘&’ ‘%d’ is the access specifier which tells compiler to take integer value as ainpute whereas. ‘&a’ tells compile to store the taken value at the address of variable ‘a’.
In the ninth instruction compiler will print me value of ‘C’ so the output of 9th instruction is as follows.
Addition is 5 [Note : considering a = 2 and b = 3]
In the tenth instruction compiler will print me address of variable C.
So the output of lenth instruction is as follows. Address of variable C is 1020.
Now consider the following program.
#include<stdio.h>
#include<conio.h>
void main()
{
inta,b,c;
printf(“Enter two numbers”);
scanf(“%d %d”, & a, &b);
c=a+b;
printf(“\n Addition is %d”,C);
printf(“\n Address of variable C is %d”,&C);
printf(‘\n value of variable C is %d”, *(&C));
getch();
}
Now, we all are clear about the output of instruction 9 and 10.
In the 11th instruction, operator *and & is used. ‘*’ operator tells compile to pickup the value which is stored at the address of variable C. So the output of 11th instruction is as follow. Value of variable C is 5 [considering a = 24 b = 3;]
Declaration of Pointer
Pointers are declare with the help of operator ‘*’. ‘*’ is known as ‘value at address’. Pointers are the variables which are used to store the address of another variable As the address of variable is always whole numbers so pointer always contains whole numbers. The declaration of pointer are as follows.
Syntax : Data type * pointer Name.
Example: int *I;
Data type defines the type of value defined at the address of pointer variable. In the above example value at the address of ‘I’ is of type integer.
Consider the following program.
# include<stdio.h>
# include<conio.h>
void main()
{
int a,b,c;
int *p,*q,*r;
p=&a;
q=&b;
r=&c;
printf(“Enter two numbers”);
scanf(“%d%d,&a,&b);
c=a + b;
printf(“\n Address of variable C is %d”,&C);
printf(“\n Address of variable C is %d,r);
printf(“\n Address of variable r is %d”,&r);
printf(“\n value of variable C is %d”,C);
printf(“\n value of variable C is %d,*^);
getch ();
}
In the above program variable ‘r’ is the integer pointer which holds the address of variable ‘C’
Case 1: In ‘printf’ statement whenever we used (“%d”,r) men me value of r is printed but ‘r’ is holding the address of variable ‘C’. so, address of variable C is copied to the value of ‘r’ and it is printed on output screen
Case 2: Whenever we used (“%d”,&r) in ‘printf’ function men the address of variable ‘r’ is pointed on o/p screen.
Case 3: When we used (“%d”,*r) in pointf function at mat time value which is stored at the address which holds by variable ‘r’ is printed.
Now me variable ‘r’ is holding the address of variable ‘C’. So, the value which is stored at the address of ‘C’ is printed on the output screen.
Consider the following example.
#include<stdio.h>
#include<conio.h>
void main()
{
int a=3;
int *p;
p=&a;
printf(“\n%d”,a);
printf(“\n%d”,&a);
printf(“\n%d”,P);
printf(“\n%d”,&P);
printf(“\n%d”,*P);
printf(“\n%d”,*(&a));
}
Run the above program on the computer system so that you will familiar with the basic use of pointers. Following is the explanation O/p of above program.
- The first ‘printf’ statement prints the value of ‘C’ ie. 3
- The second ‘printf’ statement prints the address of ‘a’
- The third ‘printf’ statement prints me value of ‘p’ ie. the address of ‘a’
- The forth ‘printf’ statement prints the address of ‘p’
- The fifth ‘printf’ statement prints the value which is stored at the address holds in ‘p’ ie. 3
- The sixth ‘printf’ statement prints the value which is stored at the address of ‘a’ ie. 3
Data type of pointer variable can be anything. Such as char *C;
In the above instruction pointer ‘C’ is of type character so the variable ‘C’ can store the address of variable which contains character type of value. Consider the following program.
#include<stdio.h>
#include<conio.h>
void main()
{
int I,*ip;
char C, *cp;
I = 3;
ip = & I;
c=’M’;
cp=&c;
printf(“%d”,I);
printf(“\n%d”,*ip);
printf(“\n%C;,C);
printf(“\n%c”, *cp);
getch();
}
The output of above program is.
3
3
m
m
Advantages of pointer
1. With the help of pointer, programmer can pass the value to the function by using call be reference.
2. Dynamic memory allocation is positive because of pointer.
3. Pointers are useful in designing linked list and other algorithmic data structure.
4. Faster access of data is positive because of pointer as pointer points to physical memory locations.
There are 4 main types of preprocessor directives:
- Macros
- File Inclusion
- Conditional Compilation
- Other directives
- Macros: Macros are a piece of code in a program which is given some name. Whenever this name is encountered by the compiler the compiler replaces the name with the actual piece of code. The ‘#define’ directive is used to define a macro. Let us now understand the macro definition with the help of a program:
#include <stdio.h> // macro definition #define LIMIT 5 int main() { for (int i = 0; i < LIMIT; i++) { printf("%d \n",i); } return 0; } |
Output:
0
1
2
3
4
In the above program, when the compiler executes the word LIMIT it replaces it with 5. The word ‘LIMIT’ in the macro definition is called a macro template and ‘5’ is macro expansion.
Macros with arguments: We can also pass arguments to macros. Macros defined with arguments works similarly as functions.
|
Output:
Area of rectangle is: 50
The compiler finds AREA(l, b) in the program it replaces it with the statement (l*b) . The values passed to the macro template AREA(l, b) will also be replaced in the statement (l*b). Therefore AREA(10, 5) will be equal to 10*5.
- File Inclusion: This type of pre-processor directive tells the compiler to include a file in the source code program. There are two types of files which can be included by the user in the program:
- Header File or Standard files: These files contains definition of pre-defined functions like printf(), scanf() etc. These files must be included for working with these functions. Different function is declared in different header files. For example, standard I/O functions are in ‘iostream’ file whereas functions which perform string operations are in ‘string’ file.
Syntax:
- Header File or Standard files: These files contains definition of pre-defined functions like printf(), scanf() etc. These files must be included for working with these functions. Different function is declared in different header files. For example, standard I/O functions are in ‘iostream’ file whereas functions which perform string operations are in ‘string’ file.
#include< file_name >
where file_name is the name of file to be included. The ‘<‘ and ‘>’ brackets tells the compiler to look for the file in standard directory.
2. user defined files: When a program becomes extremely large, it is good practice to divide it into smaller files and include whenever needed. These types of files are user defined files.
These files can be included as:
3. #include"filename"
- Conditional Compilation: Conditional Compilation directives are type of directives which helps to compile a specific portion of the program or to skip compilation of some specific part of the program based on some conditions. This can be done with the help of two pre-processing commands ‘ifdef‘ and ‘endif‘.
Syntax: - #ifdef macro_name
- statement1;
- statement2;
- statement3;
- .
- .
- .
- statementN;
- #endif
If the macro with name as ‘macroname‘ is defined then the block of statements will execute normally but if it is not defined, the compiler will simply skip this block of statements.
- Other directives: Apart from the above directives there are two more directives which are not commonly used. These are:
- #undef Directive: The #undef directive is used to undefine an existing macro. This directive works as:
- #undef LIMIT
Using this statement will undefine the existing macro LIMIT. After this statement every “#ifdef LIMIT” statement will evaluate to false.
3. #pragma Directive: This directive is a special purpose directive and is used to turn on or off some features. This type of directives is compiler-specific, that vary from compiler to compiler.
Some of the #pragma directives are discussed below:
- #pragma startup and #pragma exit: These directives helps us to specify the functions that are needed to run before program startup( before the control passes to main()) and just before program exit (just before the control returns from main()).
#include <stdio.h> void func1(); void func2(); #pragma startup func1 #pragma exit func2 void func1() { printf("Inside func1()\n"); }
void func2() { printf("Inside func2()\n"); } int main() { void func1(); void func2(); printf("Inside main()\n"); return 0; } |
Output:
Inside func1()
Inside main()
Inside func2()
The above code will produce the output as given below when run on GCC compilers:
Inside main()
This happens because GCC does not supports #pragma startup or exit. However, you can use the below code for a similar output on GCC compilers.
#include <stdio.h> void func1(); void func2(); void __attribute__((constructor)) func1(); void __attribute__((destructor)) func2();
void func1() { printf("Inside func1()\n"); } void func2() { printf("Inside func2()\n"); } int main() { printf("Inside main()\n"); return 0; }
|
- #pragma warn Directive: This directive is used to hide the warning message which are displayed during compilation.
We can hide the warnings as shown below:- #pragma warn -rvl: This directive hides those warning which are raised when a function which is supposed to return a value does not returns a value.
- #pragma warn -par: This directive hides those warning which are raised when a function does not uses the parameters passed to it.
- #pragma warn -rch: This directive hides those warning which are raised when a code is unreachable. For example: any code written after the return statement in a function is unreachable.
References:
- The C programming language by Dennis Ritchie
- C programming by K.N. King
- The Complete Reference C Fourth Edition by Herbert Schilt
- Computer Fundamentals and Programming in C by Reema Theraja.
- C in a nutshell by Peter Prinz.