PPC Unit 4 Ref Material

Download as pdf or txt
Download as pdf or txt
You are on page 1of 23

UNIT-IV 10 Hours

Structures: Defining a structure, Declaring structure variables, Accessing structure members,


Initialization, Arrays of structure, Arrays within structures, Structures within structures,
Example programs.
Pointers: Introduction, Accessing the address of a variable, Declaring and initialization of
pointer variables, Pointers as function arguments , Example programs.
Command-line arguments.
Structures: Defining a structure, Declaring structure variables, Accessing structure members,
Initialization, Arrays of structure, Arrays within structures, Structures within structures,
Example programs.

Structures: Defining a structure, Declaring structure variables, Accessing structure members,


Initialization, Arrays of structure, Arrays within structures, Structures within structures,
Example programs.

Structure is a user-defined datatype in C language which allows us to combine data of


different types together. Structure helps to construct a complex data type which is more
meaningful. It is somewhat similar to an Array, but an array holds data of similar type only.
But structure on the other hand, can store data of any type, which is practically more useful.

For example: If I have to write a program to store Student information, which will have
Student's name, age, branch, permanent address, father's name etc, which included string
values, integer values etc, how can I use arrays for this problem, I will require something
which can hold data of different types together. In structure, data is stored in form of records.

Why structs in C?
Suppose, you want to store information about a person: his/her name, aadhar number, and
salary. You can create different variables name, uin and salary to store this information.

What if you need to store information of more than one person? Now, you need to create
different variables for each information per person : name1, citNo1, salary1, name2,
citNo2, salary2, etc.

A better approach would be to have a collection of all related information under a single
name Person structure and use it for every person.

Define Structures
Before you can create structure variables, you need to define its data type. To define a struct,
the struct keyword is used. struct defines a new data type which is a collection of primary and
derived data types.
Syntax

struct structureName
{
dataType member1;
dataType member2;
...
};

For example,
struct Person
{
char name[50];
int citNo;
float salary;
};

Here, a derived type struct Person is defined. Now, you can create variables of this type.

Create struct Variables


When a struct type is declared, no storage or memory is allocated. To allocate memory of a
given structure type and work with it, we need to create variables.

Here's how we create structure variables:


struct Person
{
// code
};

int main()
{
struct Person person1, person2, p[20];
return 0;
}

Another way of creating a struct variable is:


struct Person
{
// code
} person1, person2, p[20];

In both cases,
person1 and person2 are struct Person variables
p[] is a struct Person array of size 20.
Access Members of a Structure

There are two types of operators used for accessing members of a structure.
. Member operator
-> Structure pointer operator (will be discussed in the unit 4)

Suppose, you want to access the salary of person2. Here's how you can do it.

person2.salary

#include <stdio.h>
#include <string.h>

// create struct with person1 variable


struct Person
{
char name[50];
int citNo;
float salary;
} person1;

int main()
{
// assign value to name of person1
strcpy(person1.name, "Amar");

// assign values to other person1 variables


person1.uin = 1947;
person1. salary = 10000;

// print struct variables


printf("Name: %s\n", person1.name);
printf("Aadhar No.: %d\n", person1.uin);
printf("Salary: %.2f", person1.salary);

return 0;
}

Output
Name: Amar
Aadhar No.: 1947
Salary: 10000.00

In this program, we have created a struct named Person. We have also created a variable
of Person named person1. In main(), we have assigned values to the variables defined
in Person for the person1 object. strcpy(person1.name, "Amar"); person1.uin = 1947;
person1. salary = 10000;
Notice that we have used strcpy() function to assign the value to person1.name. This is
because name is a char array (C-string) and we cannot use the assignment operator = with it
after we have declared the string. Finally, we printed the data of person1.

Keyword typedef

We use the typedef keyword to create an alias name for data types. It is commonly used with
structures to simplify the syntax of declaring variables. For example, let us look at the
following code:

struct Distance
{
int feet;
float inch;
};

int main()
{
struct Distance d1, d2;
}

We can use typedef to write an equivalent code with a simplified syntax:

typedef struct Distance


{
int feet;
float inch;
} distances;

int main()
{
distances d1, d2;
}

#include <stdio.h>
#include <string.h>

// struct with typedef person


typedef struct Person
{
char name[50];
int uin;
float salary;
} person;

int main() {

// create Person variable


person p1;
// assign value to name of p1
strcpy(p1.name, "Amar");

// assign values to other p1 variables


p1.uin = 1947;
p1. salary = 10000;

// print struct variables


printf("Name: %s\n", p1.name);
printf("Aadhar No.: %d\n", p1.uin);
printf("Salary: %.2f", p1.salary);

return 0;
}

Output
Name: Amar
Aadhar No.: 1947
Salary: 10000

Here, we have used typedef with the Person structure to create an alias person.

// struct with typedef person


typedef struct Person
{
// code
} person;
Now, we can simply declare a Person variable using the person alias:
// equivalent to struct Person p1
person p1;

Nested Structures

You can create structures within a structure in C programming. For example,


struct complex
{
int imag;
float real;
};

struct number
{
struct complex comp;
int integers;
} num1, num2;

Suppose, you want to set imag of num2 variable to 11. Here's how you can do it:
num2.comp.imag = 11;
#include <stdio.h>

struct complex
{
int imag;
float real;
};

struct number
{
struct complex comp;
int integer;
} num1;

int main()
{
// initialize complex variables
num1.comp.imag = 11;
num1.comp.real = 5.25;

// initialize number variable


num1.integer = 6;

// print struct variables


printf("Imaginary Part: %d\n", num1.comp.imag);
printf("Real Part: %.2f\n", num1.comp.real);
printf("Integer: %d", num1.integer);

return 0;
}

Output
Imaginary Part: 11
Real Part: 5.25
Integer: 6

Array of Structure

We can also declare an array of structure variables, in which each element of the array will
represent a structure variable. Example : struct employee emp[5]; The below program defines
an array emp of size 5. Each element of the array emp is of type Employee.

#include<stdio.h>

void main()
{
struct Employee
{
char ename[10];
int sal;
};

struct Employee emp[5];


int i, j;

for(i = 0; i < 3; i++)


{
printf("\nEnter %dst Employee record:\n", i+1);
printf("\nEmployee name:\t");
scanf("%s", emp[i].ename);
printf("\nEnter Salary:\t");
scanf("%d", &emp[i].sal);
}
printf("\nDisplaying Employee record:\n");
for(i = 0; i < 3; i++)
{
printf("\nEmployee name is %s", emp[i].ename);
printf("\nSlary is %d", emp[i].sal);
}
}

Structure as Function Arguments

We can pass a structure as a function argument just like we pass any other variable or an
array as a function argument.

Example:
#include<stdio.h>

struct Student
{
char name[10];
int roll;
};

void show(struct Student st);

void main()
{
struct Student std;
printf("\nEnter Student record:\n");
printf("\nStudent name:\t");
scanf("%s", std.name);
printf("\nEnter Student rollno.:\t");
scanf("%d", &std.roll);
show(std);
}

void show(struct Student st)


{
printf("\nstudent name is %s", st.name);
printf("\nroll is %d", st.roll);
}

Union

Unions are conceptually similar to structures. The syntax to declare/define a union is also
similar to that of a structure. The only differences is in terms of storage. In structure each
member has its own storage location, whereas all members of union uses a single shared
memory location which is equal to the size of its largest data member.

This implies that although a union may contain many members of different types, it cannot
handle all the members at the same time. A union is declared using the union keyword.

union item
{
int m;
float x;
char c;
}it1;

This declares a variable it1 of type union item. This union contains three members each with
a different data type. However only one of them can be used at a time. This is due to the fact
that only one location is allocated for all the union variables, irrespective of their size. The
compiler allocates the storage that is large enough to hold the largest variable type in the
union.
In the union declared above the member x requires 4 bytes which is largest amongst the
members for a 16-bit machine. Other members of union will share the same memory address.
Accessing a Union Member in C

Syntax for accessing any union member is similar to accessing structure members,

union test
{
int a;
float b;
char c;
}t;

t.a; //to access members of union t


t.b;
t.c;

#include <stdio.h>

union item
{
int a;
float b;
char ch;
};

int main( )
{
union item it;
it.a = 12;
it.b = 20.2;
it.ch = 'z';

printf("%d\n", it.a);
printf("%f\n", it.b);
printf("%c\n", it.ch);

return 0;
}

Output
-26426
20.1999
z

As you can see here, the values of a and b get corrupted and only variable c prints the
expected result. This is because in union, the memory is shared among different data types.
Hence, the only member whose value is currently stored will have the memory. In the above
example, value of the variable c was stored at last, hence the value of other variables is lost.
Pointers: Introduction, Accessing the address of a variable, Declaring and initialization
of pointer variables, Pointers as function arguments, Example programs.

A Pointer in C language is a variable which holds the address of another variable of


same data type. Pointers are used to access memory and manipulate the address. Pointers are
one of the most distinct and exciting features of C language. It provides power and flexibility
to the language.

Although pointers may appear a little confusing and complicated in the beginning, but trust
me, once you understand the concept, you will be able to do so much more with C language.
Before we start understanding what pointers are and what they can do, let's start by
understanding what does "Address of a memory location" means?

Address in C
Whenever a variable is defined in C language, a memory location is assigned for it, in which
it's value will be stored. We can easily check this memory address, using the & symbol.
If var is the name of the variable, then &var will give it's address.

Let's write a small program to see memory address of any variable that we define in our
program.

#include<stdio.h>

void main()
{
int var = 7;
printf("Value of the variable var is: %d\n", var);
printf("Memory address of the variable var is: %x\n", &var);
}

Output
Value of the variable var is: 7
Memory address of the variable var is: bcc7a00

You must have also seen in the function scanf(), we mention &var to take user input for any
variable var. scanf("%d", &var); This is used to store the user inputted value to the address of
the variable var.

Concept of Pointers
Whenever a variable is declared in a program, system allocates a location i.e an address to
that variable in the memory, to hold the assigned value. This location has its own address
number, which we just saw above. Let us assume that system has allocated memory
location 80F for a variable a. int a = 10;
We can access the value 10 either by using the variable name a or by using its address 80F.
The question is how we can access a variable using it's address? Since the memory addresses
are also just numbers, they can also be assigned to some other variable. The variables which
are used to hold memory addresses are called Pointer variables.

A pointer variable is therefore nothing but a variable which holds an address of some other
variable. And the value of a pointer variable gets stored in another memory location.

Benefits of using pointers

1. Pointers are more efficient in handling Arrays and Structures.


2. Pointers allow references to function and thereby helps in passing of function as arguments
to other functions.
3. It reduces length of the program and its execution time as well.
4. It allows C language to support Dynamic Memory management.

Declaring, Initializing and using a pointer variable in C

Declaration of C Pointer variable


The general syntax of pointer declaration is,
datatype *pointer_name;

The data type of the pointer and the variable to which the pointer variable is pointing must be
the same.

Initialization of C Pointer variable

Pointer Initialization is the process of assigning address of a variable to a pointer variable. It


contains the address of a variable of the same data type. In C language address operator & is
used to determine the address of a variable. The & (immediately preceding a variable name)
returns the address of the variable associated with it.

int a = 10;
int *ptr; //pointer declaration
ptr = &a; //pointer initialization
Pointer variable always points to variables of the same datatype. For example:
float a;
int *ptr = &a; // ERROR, type mismatch

While declaring a pointer variable, if it is not assigned to anything then it contains garbage
value. Therefore, it is recommended to assign a NULL value to it,

A pointer that is assigned a NULL value is called a NULL pointer in C.

int *ptr = NULL;

Using the pointer or Dereferencing of Pointer


Once a pointer has been assigned the address of a variable, to access the value of the variable,
the pointer is dereferenced, using the indirection operator or dereferencing operator *.
Consider the following example for better understanding.

#include <stdio.h>

int main()
{
int a;
a = 10;
int *p = &a; // declaring and initializing the pointer

//prints the value of 'a'


printf("%d\n", *p);
printf("%d\n", *&a);
//prints the address of 'a'
printf("%u\n", &a);
printf("%u\n", p);

printf("%u\n", &p); //prints address of 'p'


return 0;
}

Output

10
10
3795480300
3795480300
3795480304

Points to remember while using pointers

While declaring/initializing the pointer variable, * indicates that the variable is a pointer.
The address of any variable is given by preceding the variable name with Ampersand &.
The pointer variable stores the address of a variable.

The declaration int *a doesn't mean that a is going to contain an integer value. It means
that a is going to contain the address of a variable storing integer value.
To access the value of a certain address stored by a pointer variable * is used. Here, the * can
be read as 'value at'.

Since we have learned the basics of Pointers in C, you can check out some C programs using
pointer.

Pointer to a Pointer in C(Double Pointer)

Pointers are used to store the address of other variables of similar datatype. But if you want to
store the address of a pointer variable, then you again need a pointer to store it. Thus, when
one pointer variable stores the address of another pointer variable, it is known as Pointer to
Pointer variable or Double Pointer.

Syntax:
int **p1;

Here, we have used two indirection operator(*) which stores and points to the address of a
pointer variable i.e, int *. If we want to store the address of this (double pointer) variable p1,
then the syntax would become:

int ***p2

Simple program to represent Pointer to a Pointer


#include <stdio.h>

int main() {

int a = 10;
int *p1; //this can store the address of variable a
int **p2;
/*
this can store the address of pointer variable p1 only.
It cannot store the address of variable 'a'
*/

p1 = &a;
p2 = &p1;

printf("Address of a = %u\n", &a);


printf("Address of p1 = %u\n", &p1);
printf("Address of p2 = %u\n\n", &p2);

// below print statement will give the address of 'a'


printf("Value at the address stored by p2 = %u\n", *p2);

printf("Value at the address stored by p1 = %d\n\n", *p1);

printf("Value of **p2 = %d\n", **p2); //read this *(*p2)

/*
This is not allowed, it will give a compile time error-
p2 = &a;
printf("%u", p2);
*/
return 0;
}

Output

Address of a = 2686724
Address of p1 = 2686728
Address of p2 = 2686732

Value at the address stored by p2 = 2686724


Value at the address stored by p1 = 10

Value of **p2 = 10

Explanation of the above program

p1 pointer variable can only hold the address of the variable a (i.e Number of indirection
operator(*)-1 variable). Similarly, p2 variable can only hold the address of variable p1. It
cannot hold the address of variable a.
*p2 gives us the value at an address stored by the p2 pointer. p2 stores the address
of p1 pointer and value at the address of p1 is the address of variable a. Thus, *p2 prints
address of a.
**p2 can be read as *(*p2). Hence, it gives us the value stored at the address *p2. From
above statement, you know *p2 means the address of variable a. Hence, the value at the
address *p2 is 10. Thus, **p2 prints 10.
.
Pointer and Arrays in C

When an array in C language is declared, compiler allocates sufficient memory to contain all
its elements. Its base address is also allocated by the compiler.
Declare an array arr,
int arr[5] = { 1, 2, 3, 4, 5 };

Suppose the base address of arr is 1000 and each integer requires two bytes, the five elements
will be stored as follows:

Variable arr will give the base address, which is a constant pointer pointing to arr[0].
Hence arr contains the address of arr[0] i.e 1000.
arr has two purpose -

It is the name of the array


It acts as a pointer pointing towards the first element in the array.
arr is equal to &arr[0] by default
For better understanding of the declaration and initialization of the pointer - click here. and
refer to the program for its implementation.
NOTE:
You cannot decrement a pointer once incremented. p-- won't work.
Pointer to Array
Use a pointer to an array, and then use that pointer to access the array elements. For example,
#include<stdio.h>

void main()
{
int a[3] = {1, 2, 3};
int *p = a;
for (int i = 0; i < 3; i++)
{
printf("%d", *p);
p++;
}
return 0;
}

Output
123

Syntax:
*(a+i) //pointer with an array

is same as:
a[i]

Pointer to Multidimensional Array


Let's see how to make a pointer point to a multidimensional array. In a[i][j], a will give the
base address of this array, even a + 0 + 0 will also give the base address, that is the address
of a[0][0] element.
Syntax:
*(*(a + i) + j)

Pointer and Character strings


Pointer is used to create strings. Pointer variables of char type are treated as string.
char *str = "Hello";

The above code creates a string and stores its address in the pointer variable str. The
pointer str now points to the first character of the string "Hello".
The string created using char pointer can be assigned a value at runtime.
char *str;
str = "hello";
The content of the string can be printed using printf() and puts().
printf("%s", str);
puts(str);
str is a pointer to the string and also name of the string. Therefore we do not need to use
indirection operator *.

Array of Pointers
Pointers are very helpful in handling character arrays with rows of varying lengths.
char *name[3] =
{
"Adam",
"chris",
"Deniel"
};

//without pointer
char name[3][20] =
{
"Adam",
"chris",
"Deniel"
};

In the second approach memory wastage is more, hence it is preferred to use pointer in such
cases.

Pointer Arithmetic in C
If you want to have complete knowledge of pointers, pointer arithmetic is very important to
understand. In this topic we will study how the memory addresses change when you
increment a pointer.

16 bit Machine (Turbo C)


In a 16 bit machine, size of all types of pointer, be it int*, float*, char* or double* is always 2
bytes. But when we perform any arithmetic function like increment on a pointer, changes
occur as per the size of their primitive data type.
Size of datatypes on 16-bit Machine:

Type Size (in bytes)


int or signed int 2
char 1
long 4
float 4
double 8
long double 10

Examples for Pointer Arithmetic


Now lets take a few examples and understand this more clearly.
int* i;
i++;
In the above case, pointer will be of 2 bytes. And when we increment it, it will increment by 2
bytes because int is also of 2 bytes.
float* i;
i++;
In this case, size of pointer is still 2 bytes initially. But now, when we increment it, it will
increment by 4 bytes because float datatype is of 4 bytes.
double* i;
i++;

Similarly, in this case, size of pointer is still 2 bytes. But now, when we increment it, it will
increment by 8 bytes because its data type is double.

32 bit Machine (Visual Basic C++)


The concept of pointer arithmetic remains exact same, but the size of pointer and various
datatypes is different in a 32 bit machine. Pointer in 32 bit machine is of 4 bytes.

Following is a table for Size of datatypes on 32-bit Machine :

Type Size (in bytes)


int or signed int 4
Char 2
Long 8
Float 8
Double 16

Note: We cannot add two pointers. This is because pointers contain addresses, adding two
addresses makes no sense, because you have no idea what it would point to. But we can
subtract two pointers. This is because difference between two pointers gives the number of
elements of its data type that can be stored between the two pointers.
Program for pointer arithmetic(32-bit machine)
#include <stdio.h>

int main()
{
int m = 5, n = 10, o = 0;

int *p1;
int *p2;
int *p3;

p1 = &m; //printing the address of m


p2 = &n; //printing the address of n

printf("p1 = %d\n", p1);


printf("p2 = %d\n", p2);

o = *p1+*p2;
printf("*p1+*p2 = %d\n", o);//point 1

p3 = p1-p2;
printf("p1 - p2 = %d\n", p3); //point 2

p1++;
printf("p1++ = %d\n", p1); //point 3

p2--;
printf("p2-- = %d\n", p2); //point 4

//Below line will give ERROR


printf("p1+p2 = %d\n", p1+p2); //point 5

return 0;
}

Output
p1 = 2680016
p2 = 2680012
*p1+*p2 = 15
p1-p2 = 1
p1++ = 2680020
p2-- = 2680008

Explanation of the above program:


Point 1: Here, * means 'value at the given address'. Thus, it adds the value of m and n which
is 15.
Point 2: It subtracts the addresses of the two variables and then divides it by the size of the
pointer datatype (here integer, which has size of 4 bytes) which gives us the number of
elements of integer data type that can be stored within it.
Point 3: It increments the address stored by the pointer by the size of its datatype(here 4).
Point 4: It decrements the address stored by the pointer by the size of its datatype(here 4).
Point 5: Addition of two pointers is not allowed.
Pointers as Function Argument in C
Pointer as a function parameter is used to hold addresses of arguments passed during function
call. This is also known as call by reference. When a function is called by reference any
change made to the reference variable will effect the original variable.

Example Time: Swapping two numbers using Pointer


#include <stdio.h>

void swap(int *a, int *b);

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

swap(&m, &n); //passing address of m and n to the swap function


printf("After Swapping:\n\n");
printf("m = %d\n", m);
printf("n = %d", n);
return 0;
}

/*
pointer 'a' and 'b' holds and
points to the address of 'm' and 'n'
*/
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
Output
m = 10
n = 20

After Swapping:

m = 20
n = 10

Functions returning Pointer variables


A function can also return a pointer to the calling function. In this case you must be careful,
because local variables of function doesn't live outside the function. They have scope only
inside the function. Hence if you return a pointer connected to a local variable, that pointer
will be pointing to nothing when the function ends.
#include <stdio.h>

int* larger(int*, int*);

void main()
{
int a = 15;
int b = 92;
int *p;
p = larger(&a, &b);
printf("%d is larger",*p);
}

int* larger(int *x, int *y)


{
if(*x > *y)
return x;
else
return y;
}
Output
92 is larger

Safe ways to return a valid Pointer.


Either use argument with functions. Because argument passed to the functions are declared
inside the calling function, hence they will live outside the function as well. Or,
use static local variables inside the function and return them. As static variables have a
lifetime until the main() function exits, therefore they will be available througout the
program.

Pointer to functions
It is possible to declare a pointer pointing to a function which can then be used as an
argument in another function. A pointer to a function is declared as follows,
type (*pointer-name)(parameter);

Here is an example :
int (*sum)(); //legal declaration of pointer to function
int *sum(); //This is not a declaration of pointer to function
Copy

A function pointer can point to a specific function when it is assigned the name of that
function.
int sum(int, int);
int (*s)(int, int);
s = sum;

Here s is a pointer to a function sum. Now sum can be called using function pointer s along
with providing the required argument values.
s (10, 20);
Example of Pointer to Function
#include <stdio.h>

int sum(int x, int y)


{
return x+y;
}

int main( )
{
int (*fp)(int, int);
fp = sum;
int s = fp(10, 15);
printf("Sum is %d", s);

return 0;
}

Output
25

Complicated Function Pointer example


You will find a lot of complex function pointer examples around, lets see one such example
and try to understand it.
void *(*foo) (int*);

It appears complex but it is very simple. In this case (*foo) is a pointer to the function, whose
argument is of int* type and return type is void*.
Command-line arguments.

Points have to added yet.

You might also like