Structures-Declaring and Initializing, Nested structure, Array of Structure, Passing Structures to functions, Unions, typedef, enum, Bit fields.
Pointers: Declarations, Pointer arithmetic, Pointers and functions, call by value, Call by reference, Pointers and Arrays, Arrays of Pointers, Pointers and Structures. Meaning of static and dynamic memory allocation, Memory allocation functions.
Files: File modes, File functions, and File operations, Text and Binary files, Command Line arguments Preprocessor directives. Macros: Definition, types of Macros, Creating and implementing user defined header files
1. GNA UNIVERSITY
Text and Binary files:
Files is collection of records (or) it is a place on hard disk, where data is stored
permanently.
Types of Files
There are two types of files in C language which are as follows −
Text file
Binary File
Text File
It contains alphabets and numbers which are easily understood by human
beings.
An error in a text file can be eliminated when seen.
In text file, the text and characters will store one char per byte.
For example, the integer value 4567 will occupy 2 bytes in memory, but,
it will occupy 5 bytes in text file.
The data format is usually line-oriented. Here, each line is a separate
command.
Binary file
It contains 1’s and 0’s, which are easily understood by computers.
The error in a binary file corrupts the file and is not easy to detect.
In binary file, the integer value 1245 will occupy 2 bytes in memory and in
file.
A binary file always needs a matching software to read or write it.
For example, an MP3 file can be produced by a sound recorder or audio
editor, and it can be played in a music player.
Command Line arguments:
The arguments passed from command line are called command line arguments.
These arguments are handled by main() function.
2. GNA UNIVERSITY
To support command line argument, you need to change the structure of main()
function as given below.
int main(int argc, char *argv[] )
Here, argc counts the number of arguments. It counts the file name as the first
argument.
The argv[] contains the total number of arguments. The first argument is the file
name always.
#include <stdio.h>
void main(int argc, char *argv[] ) {
printf("Program name is: %sn", argv[0]);
if(argc < 2){
printf("No argument passed through command line.n");
}
else{
printf("First argument is: %sn", argv[1]);
}
}
Output:
Program name is: D:GNA Aug-Dec'21Problem Solving in C(BCA102)BCA Lab
Programsabc.exe
No argument passed through command line.
Preprocessor directives & Macros: Definition, types of Macros:
The C Preprocessor is not a part of the compiler, but is a separate step in the
compilation process. In simple terms, a C Preprocessor is just a text substitution
tool and it instructs the compiler to do required pre-processing before the actual
compilation. We'll refer to the C Preprocessor as CPP.
All preprocessor commands begin with a hash symbol (#). It must be the first
nonblank character, and for readability, a preprocessor directive should begin in
the first column. The following section lists down all the important preprocessor
directives −
Sr.No. Directive & Description
1 #define
3. GNA UNIVERSITY
Substitutes a preprocessor macro.
2
#include
Inserts a particular header from another file.
3
#undef
Undefines a preprocessor macro.
4
#ifdef
Returns true if this macro is defined.
5
#ifndef
Returns true if this macro is not defined.
6
#if
Tests if a compile time condition is true.
7
#else
The alternative for #if.
8
#elif
#else and #if in one statement.
9
#endif
Ends preprocessor conditional.
10
#error
Prints error message on stderr.
11
#pragma
Issues special commands to the compiler, using a standardized method.
4. GNA UNIVERSITY
Preprocessors Examples
Analyze the following examples to understand various directives.
#define MAX_ARRAY_LENGTH 20
#include <stdio.h>
#include "myheader.h"
#undef FILE_SIZE
#define FILE_SIZE 42
Predefined Macros
ANSI C defines a number of macros. Although each one is available for use in
programming, the predefined macros should not be directly modified.
Sr.No. Macro & Description
1
__DATE__
The current date as a character literal in "MMM DD YYYY" format.
2
__TIME__
The current time as a character literal in "HH:MM:SS" format.
3
__FILE__
This contains the current filename as a string literal.
4
__LINE__
This contains the current line number as a decimal constant.
5
__STDC__
Defined as 1 when the compiler complies with the ANSI standard.
Let's try the following example −
#include <stdio.h>
int main() {
5. GNA UNIVERSITY
printf("File :%sn", __FILE__ );
printf("Date :%sn", __DATE__ );
printf("Time :%sn", __TIME__ );
printf("Line :%dn", __LINE__ );
printf("ANSI :%dn", __STDC__ );
}
When the above code in a file test.c is compiled and executed, it produces
the following result −
File :test.c
Date :Jun 2 2012
Time :03:36:24
Line :8
ANSI :1
Creating and implementing user defined header files:
Step1: Type this Code
int add(int a,int b)
{
return(a+b);
}
int add(int a,int b)
{
return(a+b);
}
Step 2: Save Code
Save Above Code with [.h ] Extension .
Let name of our header file be myhead [ myhead.h ]
Step 3 : Write Main Program
#include<stdio.h>
#include"myhead.h"
int main()
{
int num1 = 10, num2 = 10, num3;
num3 = add(num1, num2);
printf("Addition of Two numbers : %d", num3);
return 0;
}
6. GNA UNIVERSITY
Include Our New Header File
Instead of writing < myhead.h> use this terminology “myhead.h”
All the Functions defined in the myhead.h header file are now ready for use .
Arrays of Pointers:
#include <stdio.h>
const int MAX = 3;
int main () {
int var[] = {10, 100, 200};
int i, *ptr[MAX];
for ( i = 0; i < MAX; i++) {
ptr[i] = &var[i]; /* assign the address of integer. */
}
for ( i = 0; i < MAX; i++) {
printf("Value of var[%d] = %dn", i, *ptr[i] );
}
return 0;
}
When the above code is compiled and executed, it produces the following
result −
Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200
Pointers and Structures:
#include <stdio.h>
struct Employee
{
char name[30];
int id;
};
struct Employee emp1, emp2, *ptr1, *ptr2;
int main()
{
7. GNA UNIVERSITY
ptr1 = &emp1;
ptr2 = &emp2;
printf (" Enter the name of the Employee (emp1): ");
scanf (" %s", &ptr1->name);
printf (" Enter the id of the Employee (emp1): ");
scanf (" %d", &ptr1->id);
printf (" n Second Employee: n");
printf (" Enter the name of the Employee (emp2): ");
scanf (" %s", &ptr2->name);
printf (" Enter the id of the Employee (emp2): ");
scanf (" %d", &ptr2->id);
printf ("n Display the Details of the Employee using Structure Pointer");
printf ("n Details of the Employee (emp1) n");
printf(" Name: %sn", ptr1->name);
printf(" Id: %dn", ptr1->id);
printf ("n Details of the Employee (emp2) n");
printf(" Name: %sn", ptr2->name);
printf(" Id: %dn", ptr2->id);
return 0;
}
Output:
Enter the name of the Employee (emp1): John
Enter the id of the Employee (emp1): 1099
Second Employee:
Enter the name of the Employee (emp2): Maria
Enter the id of the Employee (emp2): 1109
Display the Details of the Employee using Structure Pointer
Details of the Employee (emp1)
Name: John
Id: 1099
Details of the Employee (emp2) Name: Maria
Id: 1109
Meaning of static and dynamic memory allocation:
8. GNA UNIVERSITY
Difference between Static and Dynamic Memory Allocation
S.No Static Memory Allocation Dynamic Memory Allocation
1 When the allocation of memory performs
at the compile time, then it is known as
static memory.
When the memory allocation is done at the
execution or run time, then it is called dynamic
memory allocation.
2 The memory is allocated at the compile
time.
The memory is allocated at the runtime.
3 In static memory allocation, while
executing a program, the memory cannot
be changed.
In dynamic memory allocation, while executing a
program, the memory can be changed.
4 Static memory allocation is preferred in an
array.
Dynamic memory allocation is preferred in the
linked list.
5 It saves running time as it is fast. It is slower than static memory allocation.
6 Static memory allocation allots memory
from the stack.
Dynamic memory allocation allots memory from
the heap.
7 Once the memory is allotted, it will remain
from the beginning to end of the program.
Here, the memory can be alloted at any time in
the program.
8 Static memory allocation is less efficient as
compared to Dynamic memory allocation.
Dynamic memory allocation is more efficient as
compared to the Static memory allocation.
9 This memory allocation is simple. This memory allocation is complicated.
Memory allocation functions:
The concept of dynamic memory allocation in c language enables the C
programmer to allocate memory at runtime. Dynamic memory allocation in c
language is possible by 4 functions of stdlib.h header file.
malloc()
calloc()
free()
malloc() allocates single block of requested memory.
9. GNA UNIVERSITY
calloc() allocates multiple block of requested memory.
free() frees the dynamically allocated memory.
malloc() function in C
The malloc() function allocates single block of requested memory.
It doesn't initialize memory at execution time, so it has garbage value
initially.
It returns NULL if memory is not sufficient.
The syntax of malloc() function is given below:
ptr=(cast-type*)malloc(byte-size)
Let's see the example of malloc() function.
#include<stdio.h>
#include<stdlib.h>
int main(){
int n,i,*ptr,sum=0;
printf("Enter number of elements: ");
scanf("%d",&n);
ptr=(int*)malloc(n*sizeof(int)); //memory allocated using malloc
if(ptr==NULL)
{
printf("Sorry! unable to allocate memory");
exit(0);
}
printf("Enter elements of array: ");
for(i=0;i<n;++i)
{
scanf("%d",ptr+i);
sum+=*(ptr+i);
}
printf("Sum=%d",sum);
free(ptr);
return 0;
}
Output
Enter elements of array: 3
10. GNA UNIVERSITY
Enter elements of array: 10
10
10
Sum=30
calloc() function in C
The calloc() function allocates multiple block of requested memory.
It initially initialize all bytes to zero.
It returns NULL if memory is not sufficient.
The syntax of calloc() function is given below:
ptr=(cast-type*)calloc(number, byte-size)
Let's see the example of calloc() function.
#include<stdio.h>
#include<stdlib.h>
int main(){
int n,i,*ptr,sum=0;
printf("Enter number of elements: ");
scanf("%d",&n);
ptr=(int*)calloc(n,sizeof(int)); //memory allocated using calloc
if(ptr==NULL)
{
printf("Sorry! unable to allocate memory");
exit(0);
}
printf("Enter elements of array: ");
for(i=0;i<n;++i)
{
scanf("%d",ptr+i);
sum+=*(ptr+i);
}
printf("Sum=%d",sum);
free(ptr);
return 0;
}
Output
11. GNA UNIVERSITY
Enter elements of array: 3
Enter elements of array: 10
10
10
Sum=30
Nested Functions:
#include <stdio.h>
main(void) {
int my_fun();
my_fun();
printf("Main Functionn");
int my_fun() {
printf("my_fun functionn");
}
printf("Done");
}
Output
my_fun function
Main Function
Done
Arrays of strings:
#include<stdio.h>
int main()
{
char names[3][20];
int i;
12. GNA UNIVERSITY
printf(”nEnter three string valuesn”);
for(i=0;i<3;i++)
gets(names[i]);
printf(”nElements of string array are”);
for(i=0;i<3;i++)
printf(“n%s”,names[i]);
return 0;
}
Output
Enter three string values
Lovejot
Ajay
Amit
Elements of string array are
Lovejot
Ajay
Amit
Passing strings to functions:
#include <stdio.h>
void Strfun(char *ptr)
{
printf("The String is : %s",ptr);
}
int main()
13. GNA UNIVERSITY
{
char buff[20]="Hello Function";
Strfun(buff);
return 0;
}
Output:
The String is : Hello Function
Pointer Arithmetic:
We can perform arithmetic operations on the pointers like addition, subtraction,
etc. However, as we know that pointer contains the address, the result of an
arithmetic operation performed on the pointer will also be a pointer if the other
operand is of type integer. In pointer-from-pointer subtraction, the result will be
an integer value. Following arithmetic operations are possible on the pointer
in C language:
Increment
Decrement
Addition
Subtraction
Comparison
Incrementing Pointer in C
If we increment a pointer by 1, the pointer will start pointing to the immediate
next location. This is somewhat different from the general arithmetic since the
value of the pointer will get increased by the size of the data type to which the
pointer is pointing.
We can traverse an array by using the increment operation on a pointer which
will keep pointing to every element of the array, perform some operation on
that, and update itself in a loop.
14. GNA UNIVERSITY
The Rule to increment the pointer is given below:
new_address= current_address + i * size_of(data type)
Where i is the number by which the pointer get increased.
32-bit
For 32-bit int variable, it will be incremented by 2 bytes.
64-bit
For 64-bit int variable, it will be incremented by 4 bytes.
Let's see the example of incrementing pointer variable on 64-bit architecture.
#include<stdio.h>
int main(){
int number=50;
int *p;//pointer to int
p=&number;//stores the address of number variable
printf("Address of p variable is %u n",p);
p=p+1;
printf("After increment: Address of p variable is %u n",p); // in our case, p will
get incremented by 4 bytes.
return 0;
}
Output:
Address of p variable is 3214864300
After increment: Address of p variable is 3214864304
15. GNA UNIVERSITY
Traversing an array by using pointer
#include<stdio.h>
void main ()
{
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;
int i;
printf("printing array elements...n");
for(i = 0; i< 5; i++)
{
printf("%d ",*(p+i));
}
}
Output
printing array elements...
1 2 3 4 5
Decrementing Pointer in C
Like increment, we can decrement a pointer variable. If we decrement a
pointer, it will start pointing to the previous location. The formula of
decrementing the pointer is given below:
new_address= current_address - i * size_of(data type)
32-bit
For 32-bit int variable, it will be decremented by 2 bytes.
64-bit
For 64-bit int variable, it will be decremented by 4 bytes.
16. GNA UNIVERSITY
Let's see the example of decrementing pointer variable on 64-bit OS.
#include <stdio.h>
void main(){
int number=50;
int *p;//pointer to int
p=&number;//stores the address of number variable
printf("Address of p variable is %u n",p);
p=p-1;
printf("After decrement: Address of p variable is %u n",p); // P will now point
to the immidiate previous location.
}
Output
Address of p variable is 3214864300
After decrement: Address of p variable is 3214864296
However, instead of subtracting a number, we can also subtract an address
from another address (pointer). This will result in a number. It will not be a
simple arithmetic operation, but it will follow the following rule.
If two pointers are of the same type,
Address2 - Address1 = (Subtraction of two addresses)/size of data type which
pointer points
Consider the following example to subtract one pointer from an another.
#include<stdio.h>
void main ()
{
int i = 100;
17. GNA UNIVERSITY
int *p = &i;
int *temp;
temp = p;
p = p + 3;
printf("Pointer Subtraction: %d - %d = %d",p, temp, p-temp);
}
Output
Pointer Subtraction: 1030585080 - 1030585068 = 3
Illegal arithmetic with pointers
There are various operations which cannot be performed on pointers. Since,
pointer stores address hence we must ignore the operations which may lead to
an illegal address, for example, addition, and multiplication. A list of such
operations is given below.
Address + Address = illegal
Address * Address = illegal
Address % Address = illegal
Address / Address = illegal
Address & Address = illegal
Address ^ Address = illegal
Address | Address = illegal
~Address = illegal
Pointers and functions:
#include <stdio.h>
double Av(int *arr, int size);
int main () {
18. GNA UNIVERSITY
int balance[5] = {1000, 2, 3, 17, 50};
double avg;
avg = Av( balance, 5 ) ;
printf("Average value is: %fn", avg );
return 0;
}
double Av(int *arr, int size) {
int i, sum = 0;
double avg;
for (i = 0; i < size; ++i) {
sum += arr[i];
}
avg = (double)sum / size;
return avg;
}
Output:
Average value is: 214.400000
Nested structure:
Let's see a simple example of the nested structure in C language.
#include <stdio.h>
#include <string.h>
struct Employee
19. GNA UNIVERSITY
{
int id;
char name[20];
struct Date
{
int dd;
int mm;
int yyyy;
}doj;
}e1;
int main( )
{
//storing employee information
e1.id=101;
strcpy(e1.name, "Sonoo Jaiswal");//copying string into char array
e1.doj.dd=10;
e1.doj.mm=11;
e1.doj.yyyy=2014;
//printing first employee information
printf( "employee id : %dn", e1.id);
printf( "employee name : %sn", e1.name);
printf( "employee date of joining (dd/mm/yyyy) : %d/%d/%dn",
e1.doj.dd,e1.doj.mm,e1.doj.yyyy);
return 0;
20. GNA UNIVERSITY
}
Output:
employee id : 101
employee name : Sonoo Jaiswal
employee date of joining (dd/mm/yyyy) : 10/11/2014
Array of Structure:
An array of structres in C can be defined as the collection of multiple
structures variables where each variable contains information about different
entities. The array of structures in C are used to store information about
multiple entities of different data types. The array of structures is also known
as the collection of structures.
Let's see an example of an array of structures that stores information of 5
students and prints it.
#include<stdio.h>
#include <string.h>
21. GNA UNIVERSITY
struct student{
int rollno;
char name[10];
};
int main(){
int i;
struct student st[5];
printf("Enter Records of 5 students");
for(i=0;i<5;i++){
printf("nEnter Rollno:");
scanf("%d",&st[i].rollno);
printf("nEnter Name:");
scanf("%s",&st[i].name);
}
printf("nStudent Information List:");
for(i=0;i<5;i++){
printf("nRollno:%d, Name:%s",st[i].rollno,st[i].name);
}
return 0;
}
Output:
Enter Records of 5 students
Enter Rollno:1
Enter Name:Sonoo
22. GNA UNIVERSITY
Enter Rollno:2
Enter Name:Ratan
Enter Rollno:3
Enter Name:Vimal
Enter Rollno:4
Enter Name:James
Enter Rollno:5
Enter Name:Sarfraz
Student Information List:
Rollno:1, Name:Sonoo
Rollno:2, Name:Ratan
Rollno:3, Name:Vimal
Rollno:4, Name:James
Rollno:5, Name:Sarfraz
Passing Structures to functions:
Just like other variables, a structure can also be passed to a function. We may
pass the structure members into the function or pass the structure variable at
once. Consider the following example to pass the structure variable employee to
a function display() which is used to display the details of an employee.
#include<stdio.h>
struct address
{
char city[20];
int pin;
23. GNA UNIVERSITY
char phone[14];
};
struct employee
{
char name[20];
struct address add;
};
void display(struct employee);
void main ()
{
struct employee emp;
printf("Enter employee information?n");
scanf("%s %s %d %s",emp.name,emp.add.city, &emp.add.pin,
emp.add.phone);
display(emp);
}
void display(struct employee emp)
{
printf("Printing the details....n");
printf("%s %s %d %s",emp.name,emp.add.city,emp.add.pin,emp.add.phone);
}
typedef, enum, Bit fields
typedef:
The C programming language provides a keyword called typedef, which you can
use to give a type a new name. Following is an example to define a term
BYTE for one-byte numbers −
24. GNA UNIVERSITY
typedef unsigned char BYTE;
After this type definition, the identifier BYTE can be used as an abbreviation for
the type unsigned char, for example..
BYTE b1, b2;
By convention, uppercase letters are used for these definitions to remind the
user that the type name is really a symbolic abbreviation, but you can use
lowercase, as follows −
typedef unsigned char byte;
You can use typedef to give a name to your user defined data types as well. For
example, you can use typedef with structure to define a new data type and
then use that data type to define structure variables directly as follows −
#include <stdio.h>
#include <string.h>
typedef struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
} Book;
int main( ) {
Book book;
strcpy( book.title, "C Programming");
strcpy( book.author, "Nuha Ali");
25. GNA UNIVERSITY
strcpy( book.subject, "C Programming Tutorial");
book.book_id = 6495407;
printf( "Book title : %sn", book.title);
printf( "Book author : %sn", book.author);
printf( "Book subject : %sn", book.subject);
printf( "Book book_id : %dn", book.book_id);
return 0;
}
When the above code is compiled and executed, it produces the following
result −
Book title : C Programming
Book author : Nuha Ali
Book subject : C Programming Tutorial
Book book_id : 6495407
typedef vs #define
#define is a C-directive which is also used to define the aliases for various data
types similar to typedef but with the following differences −
typedef is limited to giving symbolic names to types only where as #define can
be used to define alias for values as well, q., you can define 1 as ONE etc.
typedef interpretation is performed by the compiler whereas #define statements
are processed by the pre-processor.
The following example shows how to use #define in a program –
#include <stdio.h>
26. GNA UNIVERSITY
#define TRUE 1
#define FALSE 0
int main( ) {
printf( "Value of TRUE : %dn", TRUE);
printf( "Value of FALSE : %dn", FALSE);
return 0;
}
When the above code is compiled and executed, it produces the following result
−
Value of TRUE : 1
Value of FALSE : 0
Enum:
The enum in C is also known as the enumerated type. It is a user-defined data
type that consists of integer values, and it provides meaningful names to these
values. The use of enum in C makes the program easy to understand and
maintain. The enum is defined by using the enum keyword.
The following is the way to define the enum in C:
enum flag{integer_const1, integer_const2,.....integter_constN};
#include <stdio.h>
enum days{sunday=1, monday, tuesday, wednesday, thursday, friday,
saturday};
int main()
{
27. GNA UNIVERSITY
enum days d;
d=monday;
switch(d)
{
case sunday:
printf("Today is sunday");
break;
case monday:
printf("Today is monday");
break;
case tuesday:
printf("Today is tuesday");
break;
case wednesday:
printf("Today is wednesday");
break;
case thursday:
printf("Today is thursday");
break;
case friday:
printf("Today is friday");
break;
case saturday:
printf("Today is saturday");
break;
28. GNA UNIVERSITY
}
return 0;
}
Output
Bit Fields:
In programming terminology, a bit field is a data structure that allows the
programmer to allocate memory to structures and unions in bits in order to
utilize computer memory in an efficient manner.
Bit Field Declaration
The declaration of a bit-field has the following form inside a structure −
struct {
type [member_name] : width ;
};
The following table describes the variable elements of a bit field −
Sr.No. Element & Description
1
type
An integer type that determines how a bit-field's value is interpreted. The
type may be int, signed int, or unsigned int.
2
member_name
29. GNA UNIVERSITY
The name of the bit-field.
3
width
The number of bits in the bit-field. The width must be less than or equal
to the bit width of the specified type.
#include <stdio.h>
#include <string.h>
struct {
unsigned int age : 3;
} Age;
int main( ) {
Age.age = 4;
printf( "Sizeof( Age ) : %dn", sizeof(Age) );
printf( "Age.age : %dn", Age.age );
Age.age = 7;
printf( "Age.age : %dn", Age.age );
Age.age = 8;
printf( "Age.age : %dn", Age.age );
30. GNA UNIVERSITY
return 0;
}
When the above code is compiled it will compile with a warning and when
executed, it produces the following result −
Sizeof( Age ) : 4
Age.age : 4
Age.age : 7
Age.age : 0