Unit 4

You might also like

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 47

Unit 4

Structure Definition, typedef, Union, structure vs. union, Enumeration, bit-fields,


Pointers, pointer arithmetic, pointer to pointer, Pointer to arrays/structures/functions
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 we want to store data about a book. We might want to store its
name (a string), its price (a float) and number of pages in it (an int).

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.


Approach No1.
int main()
{
char name[3] ;
float price[3] ;
int pages[3], i ;
printf ( "\nEnter names, prices and no. of pages of 3 books\n" ) ;
for ( i = 0 ; i <= 2 ; i++ )
scanf ( "%c %f %d", &name[i], &price[i], &pages[i] );
printf ( "\nAnd this is what you entered\n" ) ;

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


printf ( "%c %f %d\n", name[i], price[i], pages[i] );
}
The program becomes more difficult to handle as the number of items relating to the
book goes on increasing.

For example, we would be required to use a number of arrays, if we also decide to store
name of the publisher, date of purchase of book, etc.

Structure

A structure contains a number of data types grouped together. These data types may or
may not be of the same type.
Approach No.2
main( )
printf ( "\nEnter names, prices & no. of pages of 3
{
books\n" ) ;
struct book scanf ( "%s %f %d", b1.name, &b1.price, &b1.pages ) ;
{ scanf ( "%s %f %d", &b2.name, &b2.price, &b2.pages ) ;
char name ; scanf ( "%cs%f %d", &b3.name, &b3.price, &b3.pages ) ;
float price ;
int pages ; printf ( "\n Data you entered" ) ;
}; printf ( "\n%c %f %d", b1.name, b1.price, b1.pages ) ;
struct book b1, b2, b3 ; printf ( "\n%c %f %d", b2.name, b2.price, b2.pages ) ;
printf ( "\n%c %f %d", b3.name, b3.price, b3.pages ) ;
}
This statement defines a new data type called struct book. Each variable of this data type
will consist of a character variable called name, a float variable called price and an integer
variable called pages.

The general form of a structure declaration statement is given below.

struct <structure name> struct book


{ {
structure element 1 ; char name ;
structure element 2 ; float price ;
...... int pages ;
...... };
};
Declaring and instantiating a Structure
struct book struct book
{ {
char name ; char name ;
float price ; float price ;
int pages ; int pages ;
}; } b1, b2, b3 ;
struct book b1, b2, b3 ;

All above mentioned declarations are same

This statement sets aside space in memory. It makes available space to hold all the
elements in the structure—in this case, 7 bytes—one for name, four for price and
two for pages. These bytes are always in adjacent memory locations.
Like primary variables and arrays, structure variables can also be initialized where they
are declared. The format used is quite similar to that used to initialize arrays.

struct book
{
char name[ 10 ] ;
float price ;
int pages ;
};
struct book b1 = { "Basic", 130.00, 550 } ;
struct book b2 = { "Physics", 150.80, 800 } ;
struct book b3 = { 0 } ;
How Structure Elements are Stored?
Whatever be the elements of a structure, they are always stored in contiguous memory locations.
# include <stdio.h>
int main( )
{
struct book
{
char name ;
float price ;
int pages ;
};
struct book b1 = { 'B', 130.00, 550 } ;
printf ( "Address of name = %u\n", &b1.name ) ;
printf ( "Address of price = %u\n", &b1.price ) ;
printf ( "Address of pages = %u\n", &b1.pages ) ;
return 0 ;
}
To store data of 100 books we would be required to use 100 different structure
variables from b1 to b100, which is definitely not very convenient.

A better approach would be to use an array of structures.


Array of Structures

#include<stdio.h> int main()


struct book {
{
char name ; int i ;
float price ; for ( i = 0 ; i <= 2 ; i++ )
int pages ; {
}; printf ( "Enter name, price and pages " ) ;
struct book b[ 3 ] ; fflush ( stdin ) ;
scanf ( "%c %f %d", &b[ i ].name, &b[ i ].price, &b[ i ].pages ) ;
}
for ( i = 0 ; i <= 2 ; i++ )
printf ( "%c %f %d\n", b[ i ].name, b[ i ].price, b[ i ].pages ) ;
return 0 ;
}
Write C program to accept the details of employee and display them using structure.
Details consist of Employee ID, Name, Designation, Department, Salary.

Write C program to read the details of two workers and calculate total payment of
workers using structure.

Write a program to add two distances in the inch-feet system


Write a program to add two distances in the inch-feet system

#include <stdio.h>
struct Distance { result.feet = d1.feet + d2.feet;
int feet; result.inch = d1.inch + d2.inch;
float inch;
} d1, d2, result; // convert inches to feet if greater than 12
while (result.inch >= 12.0)
{
int main()
result.inch = result.inch - 12.0;
{
++result.feet;
printf("Enter feet: ");
}
scanf("%d %d", &d1.feet, &d2.feet);
printf("\nSum of distances = %d %f",
printf("Enter inch: ");
result.feet, result.inch);
scanf("%f %f", &d1.inch, &d2.inch);
return 0;
}
Copying one structure instance to
another
/* copying all elements at one go */
main( ) e3 = e2 ;
printf ( "\n%s %d %f", e1.name, e1.age,
{ struct employee e1.salary ) ;
{ printf ( "\n%s %d %f", e2.name, e2.age,
char name[10] ; e2.salary ) ;
int age ; printf ( "\n%s %d %f", e3.name, e3.age,
float salary ; e3.salary ) ;
}; }
struct employee e1 = { "Sanjay", 30, 5500.50 } ;
struct employee e2, e3 ;
/* piece-meal copying */
strcpy ( e2.name, e1.name ) ;
e2.age = e1.age ; e2.name=e1.name is invalid
e2.salary = e1.salary ;
Nesting of Structures
One structure can be nested within another structure. Using this facility, complex data
types can be created.
# include <stdio.h> struct emp e = {"Amit", "989898", "Dehradun", 10 };
int main( ) printf ( "name = %s phone = %s\n", e.name, e.a.phone ) ;
{ printf ( "city = %s pin = %d\n", e.a.city, e.a.pin ) ;
struct address return 0 ;
{ }
char phone[ 15 ] ;
char city[ 25 ] ;
int pin ;
};
struct emp
{
char name[ 25 ] ;
struct address a ;
};
Passing Structure to a function via Call by Value

struct book
{
char name[25] ;
char author[25] ;
int callno ;
};
int main( )
{
struct book b1 = {"Hello", "ABC", 101 } ;
display ( b1 ) ;
}
display ( struct book b )
{
printf ( "\n%s %s %d", b.name, b.author, b.callno ) ;
}
Passing Structure to a function via Call by
Reference
struct book
{
char name[25] ;
char author[25] ;
int callno ;
};
main( )
{
struct book b1 = {"Hello", "ABC", 101 } ;
display ( &b1 ) ;
}
display ( struct book *b )
{
printf ( "\n%s %s %d", b->name, b->author, b->callno ) ;
}
Typedef

The typedef is a keyword that is used to provide existing data types with a new name. The
C typedef keyword is used to redefine the name of already existing data types.

Syntax of typedef

typedef <existing_name> <alias_name>

For example, consider the following statement in which the type unsigned long int is
redefined to be of the type NEWTYPE:

typedef unsigned long int NEWTYPE ;


Now we can declare variables of the type unsigned long int by writing,

NEWTYPE var1, var2 ;


instead of
#include <stdio.h> unsigned long int var1, var2 ;
int main()
{
typedef unsigned int unit;
unit i,j;
i=10;
j=20;
printf("Value of i is :%d",i);
printf("\nValue of j is :%d",j);
return 0;
}
Using typedef with structures
struct student
{
char name[15];
int age;
};
struct student s1;
we use the typedef keyword to create the variable of type student.
The same typedef can be written as:
struct student
{ typedef struct student
char name[20]; {
int age; char name[20];
}; int age;
typedef struct student stud; } stud;
stud s1, s2; stud s1,s2;
#include <stdio.h>
typedef struct student
{
char name[20];
int age;
}stud;
int main()
{
stud s1;
printf("\nEnter name");
scanf("%s",&s1.name);
printf("\nEnter age");
scanf("%d",&s1.age);
printf("\n Name of the student is : %s", s1.name);
printf("\n Age of the student is : %d", s1.age);
return 0;
}
Using typedef with Arrays
#include<stdio.h>
typedef int Arr[4];

int main()
{
Arr temp = { 10, 20, 30, 40 };
printf("typedef using an array\n");

for (int i = 0; i < 4; i++) {


printf("%d ", temp[i]);
}
return 0;
}
Typecasting
Sometimes we are required to force the compiler to explicitly convert the value of an
expression to a particular data type.
# include <stdio.h>
# include <stdio.h>
int main( )
int main( )
{
{
float a ;
float a ;
int x = 6, y = 4 ;
int x = 3, y = 2 ;
a = ( float ) x / y ;
a=x/y;
printf ( "Value of a = %f\n", a ) ;
printf ( "Value of a = %f\n", a ) ;
return 0 ;
return 0 ;
}
}

Output will be 1.500000


Output will be 1.000000
Unions
Unions are derived data types I(user defined), the way structures are. It contain
elements of the different data types just like structure.

But while a structure enables us treat a number of different variables stored at different
places in memory, a union enables us to treat the same space in memory as a number
of different variables.

All the members in the C union are stored in the same memory location. Due to this,
only one member can store data at the given instance.

That is, a union offers a way for a section of memory to be treated as a variable of one
type on one occasion, and as a different variable of a different type on another
occasion.
Syntax of Union in C
union union_name {
datatype member1;
datatype member2;
...
};

Different Ways to Define a Union Variable

1. Defining Union Variable with Declaration


union union_name {
datatype member1;
datatype member2;
...
} var1, var2, ...;
2. Defining Union Variable after Declaration

union union_name {
datatype member1;
datatype member2;
...
};

union union_name var1, var2, var3...;


# include <stdio.h>
int main( )
{
union a
{
short int i ;
char ch[ 2 ] ;
};
union a key ;

key.i = 512 ;
printf ( "key.i = %d\n", key.i ) ;
printf ( "key.ch[ 0 ] = %d\n", key.ch[ 0 ] ) ;
printf ( "key.ch[ 1 ] = %d\n", key.ch[ 1 ] ) ;
return 0 ;
}
Size of Union
The size of the union will always be equal to the size of the largest member of the array. All
the less-sized elements can store the data in the same space without any overflow.

512 is an integer, a 2 byte number. Its binary equivalent will be 0000 0010 0000 0000.
union abc{
int a;
char b;
float c;
double d;
};
int main()
{
printf("Size of union abc is %d", sizeof(union abc));
return 0;
}

The size of int is 4 bytes, size of char is 1 byte, size of float is 4 bytes, and the size of double
is 8 bytes. Since the double variable occupies the largest memory among all the four
variables, so total 8 bytes will be allocated in the memory.
The following table lists the key difference between the structure and union in C:

Structure Union
The size of the structure is equal to or
greater than the total size of all of its The size of the union is the size of its
members. largest member.

The structure can contain data in Only one member can contain data at
multiple members at the same time. the same time.
It is declared using the struct keyword. It is declared using the union keyword.
Enumerated Data Type
The enumerated data type gives you an opportunity to invent your own data type and
define what values the variable of this data type can take.
This can help in making the program listings more readable, which can be an advantage
when a program gets complicated or when more than one programmer would be
working on it.
one could invent a data type called sports which can have four possible values— cricket,
tennis, football or hockey.

enum sports
{
cricket, tennis, football, hockey
};
enum sports person1, person2 ;
Like structures, this declaration has two parts:

(a) The first part declares 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:


person1 = cricket ;
person2 = football ;

we can’t use values that aren’t in the original declaration

Person1 = volleyball; //generates an error


Internally, the compiler treats the enumerators as integers.

Each value on the list of permissible values corresponds to an integer, starting with 0.

Thus, in our example, cricket is stored as 0, tennis is stored as 1, football as 2 and hockey
as 3.

This way of assigning numbers can be overridden by the programmer by initializing the
enumerators to different integer values

enum sports
{
cricket = 100, tennis = 200, football = 300, hockey = 400
};
enum sports person1, person2 ;
include <stdio.h>
# include <string.h> strcpy ( e.name, " Ajay" ) ;
int main( ) e.age = 32 ;
{ e.bs = 5000 ;
enum emp_dept e.department = manufacturing ;
{
assembly, manufacturing, accounts, stores printf ( "Name = %s\n", e.name ) ;
}; printf ( "Age = %d\n", e.age ) ;
struct employee printf ( "Basic salary = %f\n", e.bs ) ;
{ printf ( "Dept = %d\n", e.department ) ;
char name[ 30 ] ;
int age ;
float bs ;
enum emp_dept department ;
};
struct employee e ;
Bit Fields

In C language, we have union and struct data types where we can declare user-defined
data types. The size of the struct depends on data members. But sometimes, we do not
need such a huge size of the data type, because it occupies memory, and it creates a
waste of memory.

If in a program a variable is to take only two values 1 and 0, we really need only a single
bit to store it. Similarly, if a variable is to take values from 0 to 3, then two bits are
sufficient to store these values.

Bit-fields are variables that are defined using a predefined width or size.

data_type member_name : width_of_bit-field;


#include <stdio.h>

struct date {
unsigned int d;
unsigned int m;
unsigned int y;
};

int main()
{
printf("Size of date is %lu bytes\n", sizeof(struct date));
struct date dt = { 18, 10, 2023 };
printf("Date is %d/%d/%d", dt.d, dt.m, dt.y);
}
#include <stdio.h>

struct date {
int d:6;
int m:5;
int y;
};

int main()
{
printf("Size of date is %lu bytes\n",
sizeof(struct date));
struct date dt = { 18, 10, 2023 };
printf("Date is %d/%d/%d", dt.d, dt.m, dt.y);
}
Pointers to Functions

Pointers can also point to C functions. If we know the function’s address, we can point to it,
which provides another way to invoke it.

# include <stdio.h>
void display( ) ;
int main( )
{
printf ( "Address of function display is %u\n", display ) ;
display( ) ;
return 0 ;
}
void display( )
{
puts ( “Function Called" ) ;
}
# include <stdio.h>
void display( ) ;
int main( )
{
void ( *func_ptr )( ) ;
func_ptr = display ;
printf ( "Address of function display is %u", func_ptr ) ;
( *func_ptr )( ) ;
return 0 ;
}
void display( ) void ( *func_ptr )( ) ;
{ means is, that func_ptr is a pointer to a
puts ( "\nLong live viruses!!" ) ; function, which returns nothing
}
Pointer Arithmetic x++ ;
y++ ;
# include <stdio.h> z++ ;
int main( ) printf ( "New address in x = %u\n", x ) ;
{ printf ( "New address in y = %u\n", y ) ;
int i = 3, *x ; printf ( "New address in z = %u\n", z ) ;
float j = 1.5, *y ; return 0 ;
char k = 'c', *z ; }
printf ( "Value of i = %d\n", i ) ;
printf ( "Value of j = %f\n", j ) ;
printf ( "Value of k = %c\n", k ) ;
x = &i ;
y = &j ;
z = &k ;
printf ( "Original address in x = %u\n", x ) ;
printf ( "Original address in y = %u\n", y ) ;
printf ( "Original address in z = %u\n", z ) ;
Addition of Integer to Pointer
When a pointer is added with an integer value, the value is first multiplied by the size of
the data type and then added to the pointer.

For Example:
Consider the same example as above where the ptr is an integer pointer that stores 1000
as an address. If we add integer 5 to it using the expression, ptr = ptr + 5, then, the final
address stored in the ptr will be ptr = 1000 + sizeof(int) * 5 = 1020.
#include <stdio.h>
int main()
{
int N = 4;
int *ptr1, *ptr2;
ptr1 = &N;
ptr2 = &N;
printf("Pointer ptr2 before Addition: ");
printf("%p \n", ptr2);

ptr2 = ptr2 + 3;
printf("Pointer ptr2 after Addition: ");
printf("%p \n", ptr2);

return 0;
}
Subtraction of Pointers
#include <stdio.h>
int main()
{
int x = 6;
int N = 4;
int *ptr1, *ptr2;

ptr1 = &N;
ptr2 = &x;

printf(" ptr1 = %u, ptr2 = %u\n", ptr1, ptr2);


x = ptr2 - ptr1;
printf("Subtraction of ptr1 " "& ptr2 is %d\n",x);

return 0;
}
The subtraction of two pointers is possible only when they have the same data
type. The result is generated by calculating the difference between the addresses
of the two pointers and calculating how many bits of data it is according to the
pointer data type.
Comparison of Pointers
We can compare the two pointers by using the comparison operators in C. We can
implement this by using all operators in C >, >=, <, <=, ==, !=. It returns true for the valid
condition and returns false for the unsatisfied condition.
#include <stdio.h> if (ptr1 == ptr2) {
printf("Pointer to Array and First Element are Equal.");
int main() }
{ else {
int arr[5]; printf("Pointer to Array and First Element are not Equal.");
int* ptr1 = &arr; }
int* ptr2 = &arr[0];
return 0;
}
Comparison to NULL
A pointer can be compared or assigned a NULL value irrespective of what is the pointer
type. Such pointers are called NULL pointers.

#include <stdio.h>
int main()
{
int* ptr = NULL;

if (ptr == NULL) {
printf("The pointer is NULL");
}
else {
printf("The pointer is not NULL");
}
return 0;
}
Pointer Comparison in Array
for (int i = 0; i < n; i++) {
#include <stdio.h>
if (*ptr % 2 == 0) {
int main()
count_even++;
{
}
int n = 10; // length of an array
if (*ptr % 2 != 0) {
count_odd++;
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
}
int* ptr;
ptr++;
}
ptr = arr;
printf("No of even elements in an array is : %d",
int count_even = 0;
count_even);
int count_odd = 0;
printf("\nNo of odd elements in an array is : %d",
count_odd);
}

You might also like