0% found this document useful (0 votes)
25 views168 pages

C Class

Uploaded by

Sneha Sandhya
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views168 pages

C Class

Uploaded by

Sneha Sandhya
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

1

DATE
CONTENT PAGE NO.
2021
JUNE 1 SIZE OF OPERATOR 7
IMPLICIT AND EXPLICIT
COMPILER OPTIMISATION
JUNE 2 SHORT CIRCUIT 11
JUNE 3 SHIFTING 15
JUNE 4 BITWISE OPERATORS 20
MASKING
JUNE 5 SET BITS 23
CLEAR BIT
TOGGLING -> XOR
JUNE 7 TERNARY OPERATOR 26
COMMA OPERATOR
OVERFLOW
UNDERFLOW
JUNE 8 ARRAYS 28
WAYS OF DECLARING ARRAYS
REVERSE THE ARRAY
JUNE 9 BUBBLE SORT 33
CLOCK WISE ROTATION
CONTINUE
FUNCTIONS - INTRO
TRUNCATE TO INT IN FUNCTION
JUNE 10 ADVANTAGES OF FUNCTION 36
VOID AND RETURN TYPE FUNCTION
ACTUAL AND FORMAL ARGUEMENTS
FUNCTION AND THE STACK
JUNE 11 TYPES OF FUNCTIONS 40
PROGRAM OPTIMISATION
JUNE 14 POINTERS – WHY ? 43
RULES OF POINTERS
1. POINTER IS AN INTEGER
2

2.REFERENCING AND REFERENCING


3. POINTING MEANS CONTAINING
JUNE 15 4. CONTINUATION 46
ENDIANESS
POINTER ARGUMENTS IN FUNCTION
JUNE 16 5.ENDIANESS 49
6.POINTER ARITHMETIC
WAYS OF POINTING THE NEXT ELEMENTS
JUNE 17 FUNCTION PROTOTYPE 53
FUNCTION STACK
FACTORIAL
MAIN RECURSIVE -> NOT TRUE RECURSIVE
JUNE 21 BUFFER STREAM 56
FORMATTED AND UNFORMATTED I/O
STDOUT & STDERR
JUNE 22 I/O FORMATTED 60
JUNE 23 RETURN TYPES OF BUILT IN FUNCTIONS 64
FORMATTED AND UNFORMATTED
JUNE 24 BUFFERS – TEMPORARY STORAGE 69
DISABLING THE OUTPUT BUFFER
BUFFER – WAYS TO BE FLUSHED
SIZE OF RETURN TYPE
JULY 25 STRINGS 73
WAYS TO CREATE STRING
ARRAY AND STRING
STRING LITERAL IN CODE SEGMENT
CODE SEGMENT VS STACK
JUNE 28 STRING SHARING 77
SAME ADDRESS IN CODE SEGMENT
VALID INITISATIONS OF STRING
3

SIZEOF OF STRING
STRLEN OF STRINGS
CONST CHAR *
GETS -> NOT RECOMMENDED
JUNE 29 POINTER THAT CAUSES SEGMENTATION FAULT 82
STRCPY
MY_STRCPY
STRCMP
MY_STRCMP
JUNE 30 STRSTR
-HAYSTACK & NEEDLE 86
STRCAT
STRING TOKEN
MY_ATOI() FUNCTION
JULY 2 STORAGE CLASSES 92
BSS
UNINITIALISED
JULY 3 STATIC 94
GLOBAL IN DS
JULY 5 EXTERN 98
PRIORITY IS GIVEN TO GLOBAL THEN EXTERN
JULY 6 STATIC FOLLOWS NON-STATIC 100
CONFLICTING TYPES OF EXTERN
EXTERN BLOCK INITIALISATION - ERROR
STATIC FUNCTION SCOPE – WITHIN FILE
EXTERN WORKING AS LINKAGE OR GLOBAL
JULY 7 VOID POINTER 105
JULY 8 NULL POINTER – POINTING TO NOTHING 107
TYPECASTING OF VOID POINER
SIZEOF(VOID *) == SIZE OF CHAR
4

STATIC MEMORY
DYNAMIC MEMORY
STATIC & DYNAMIC MEMORY
CALLOC, REALLOC, MALLOC, FREE -> STDLIB.H
JULY 10 DYNAMIC – HEAP MEMORY 110
MALLOC VS CALLOC
DANGLING POINTER
JULY 13 CONST 114
DIFFERENT CONST TYPES
DO’s AND DONT’s POINTER ARITHMETIC
BUS ERROR
JULY 14 MULTILEVEL POINTER 118
DIFFERENT WAYS OF INTERPRETING 2D ARRAYS
JULY 15 2D -> 1D -> ARRAY ELEMENTS 120
OUTSIDE POINTER, INSIDE POINTER
ARRAY OF STRINGS
JULY 16 POINTER TO AND ARRAY 122
2D ARRAY DYNAMICALLY
BOTH STATIC
STATIC , DYNAMIC
DYNAMIC, STATIC
BOTH DYNAMIC
JULY 19 ADVANCED FUNCTIONS 124
COMMAND LINE ARGUMENTS
ADD VARIABLES AND VALUE TO ENVIRONMENTAL
SETENV, GETENV
FUNCTION POINTER
JULY 20 CALLING A FUNCTION THROUGH POINTER 128
ARRAY OF FUNCTION POINTERS
ATEXIT() -> EXECUTES IN REVERSE ORDER
5

JULY 21 GSORT() 132


GENERIC FUNCTION
VARIADIC FUNCTION -> VARIABLE ARGUMENTS
va_list, va_start, va_arg, va_end
JULY 22 STAGES INVOLVED IN COMPILATION 136
1.PREPROCESSING
1.INCLUSION OF HEADER FILE
2.REMOVING OF COMMENTS
3.SUBSTITUTION OF MACROS
4.CONDITIONAL COMPILATION
2.COMPILATION
3.ASSEMBLY
4.LINKING
JULY 24 PREPROCESSOR DIRECTIVES 137
PREDEFINED MACROS
FUNCTION LIKE MACROS
JULY 26 MULTILINE MACROS 140
FUNCTION Vs MACRO
WARNING, ERROR
#pragma -> not portable
CONDITIONAL COMPILATION
JULY 27 USER DEFINED DATATYPES 145
DERIVED WITH
1.STRUCTURES
2.UNIONS
3.TYPEDEFS
4.ENUM
JULY 28 STRUCT DEFINITION & INITIALISATION 151
STRUCTURE TO STRUCTURE ASSIGNING
STRUCTURE PADDING
DISK FRAGMENTATION
JULY 29 Pragma pack(2 power values) 155
BITFIELDS
6

UNIONS -> SAME MEMORY FOR VARIABLES


JULY 30 TYPEDEF -> ANOTHER NAME FOR VAR, FUNCTIONS 159
TYPEDEF FOR STRUCTURE
FOR FUNCTION POINTER
MORE THAN ONE ALIAS
ENUM -> CONTINUOUS AUTOMATIC ASSIGNING
AUG 2 FILE POINTERS 164
MODES OF OPERATIONS
READ MODE
WRITE MODE
ferror(fptr)
REWIND
AUG 3 FSEEK 167
FWRITE
VOLATILE
7

JUNE 1
SIZEOF IS A COMPILE TIME OPERATOR, NEVER EXECUTE THE OPERATION AND STORE IT

#include <stdio.h>
int main()
{
int num1 = 5;
int num2 = sizeof(++num1); //num2 stores the size 4, sizeof is a compile
time operator does not make the change
printf(“num1 is %d and num2 is %d\n”, num1, num2);
return 0;
}

output:
num1 is 5 and num2 is 4
-----------------------------------------------------------------------------------
DATA TYPE INITIALISATION OF FLOAT

1) #include <stdio.h>
int main()
{
int x=10,y=4,z;
z=x/y; // z=int/int ==>int
printf(“z= %f\n”,z);
return;
}

output:
z=2
-----------------------------------------------------------------------------------
2) #include <stdio.h>
int main()
{
int x=10,y=4;
float z=x/y; // z=int/int ==>float but without decimal values
printf(“z= %f\n”,z);
return;
}

output:
z=2.0000

-----------------------------------------------------------------------------------
3) #include <stdio.h>
int main()
{
int x=10,;
float y=4; z
z=x/y; // z=int/float ==>float with decimal values (implict
conversion by compiler)
printf(“z= %f\n”,z);
return;
}

output:
z=2.5000
-----------------------------------------------------------------------------------
8

4) #include<stdio.h>
int main()
{
int x=0;
float y=4,z;
z=x/y; //implicit conversion the x is treated as float only during
the execution
printf("x=%d,y=%f,z=%f\n",x,y,z);
return 0;
}

./a.out
x=0,y=4.000000,z=0.000000

-----------------------------------------------------------------------------------
5)#include<stdio.h>
int main()
{
int x=10,y=4;
float z;
z=(float)x/y; //explicit conversion by programmer
printf("x=%d,y=%d,z=%f\n",x,y,z);
return 0;
}

./a.out
x=10,y=4,z=2.500000
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int x=10,y=4;
float z;
z=x/(float)y; //for y as explicit float it has the same output
printf("x=%d,y=%d,z=%f\n",x,y,z);
return 0;
}

./a.out
x=10,y=4,z=2.500000

-----------------------------------------------------------------------------------

char x=12,y=20,z; //one byte data type


z=x+y; //int/int

internally character is always converted into integer

char x=12;
short int y=20.x;
z=x+y; //char+int ==>int

LR+HR-->LR CONVERTED TO HR
9

#include<stdio.h>
int main()
{
char x=12,y=20,z;
printf("z=%zu\n",sizeof(x+y));
return 0;
}
./a.out
z=4 //size
-----------------------------------------------------------------------------------
Type promotion (DEPENDS ON LHS)

LHS type is HR and RHS type is LR → int = char → LR is promoted
to HR while assigning

Type demotion

LHS is LR and RHS is HR → int = float → HR rank will be demoted
to LR. Truncated
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int num=0;
num=num++ + ++num +num++;
num=num++; //undefined output
printf("%d",num);
}

./a.out
4

-----------------------------------------------------------------------------------

COMPILER OPTIMISATION

#include<stdio.h>
int main()
{
int num1=1, num2=0;
if (++num1 || num2++) // if ++num1 is true it wont go to num2++
{
printf(“num1 is %d num2 is %d\n”, num1, num2);
}
num1 = 1, num2 = 0;

else
{
printf(“num1 is %d num2 is %d\n”, num1, num2);
}
return 0;
}

output:
num1 is 2 num2 is 0
-----------------------------------------------------------------------------------
10

#include<stdio.h>
int main()
{
int num1=1, num2=0;
if (num1++ || ++num2) // if ++num1 is true it wont go to num2++
{
printf(“num1 is %d num2 is %d\n”, num1, num2);
}
num1 = 1, num2 = 0;

else
{
printf(“num1 is %d num2 is %d\n”, num1, num2);
}
return 0;
}

output:
num1 is 2 num2 is 0
-----------------------------------------------------------------------------------

#include<stdio.h>
int main()
{
int num1=0, num2=1;
if (num1++ || ++num2)
{
printf(“num1 is %d num2 is %d\n”, num1, num2);
}
num1 = 1, num2 = 0;

else
{
printf(“num1 is %d num2 is %d\n”, num1, num2);
}
return 0;
}

output:
num1 is 1 num2 is 2
-----------------------------------------------------------------------------------
11

JUNE 2
SIZEOF IS A COMPILE TIME OPERATOR, NEVER EXECUTE THE OPERATION AND STORE IT

#include <stdio.h>
int main()
{
int num1 = 5;
int num2 = sizeof(++num1); //num2 stores the size 4, sizeof is a compile
time operator does not make the change
printf(“num1 is %d and num2 is %d\n”, num1, num2);
return 0;
}

output:
num1 is 5 and num2 is 4
-----------------------------------------------------------------------------------
DATA TYPE INITIALISATION OF FLOAT

1) #include <stdio.h>
int main()
{
int x=10,y=4,z;
z=x/y; // z=int/int ==>int
printf(“z= %f\n”,z);
return;
}

output:
z=2
-----------------------------------------------------------------------------------
2) #include <stdio.h>
int main()
{
int x=10,y=4;
float z=x/y; // z=int/int ==>float but without decimal values
printf(“z= %f\n”,z);
return;
}

output:
z=2.0000

-----------------------------------------------------------------------------------
3) #include <stdio.h>
int main()
{
int x=10,;
float y=4; z
z=x/y; // z=int/float ==>float with decimal values (implict
conversion by compiler)
printf(“z= %f\n”,z);
return;
}

output:
z=2.5000
-----------------------------------------------------------------------------------
12

4) #include<stdio.h>
int main()
{
int x=0;
float y=4,z;
z=x/y; //implicit conversion the x is treated as float only during
the execution
printf("x=%d,y=%f,z=%f\n",x,y,z);
return 0;
}

./a.out
x=0,y=4.000000,z=0.000000

-----------------------------------------------------------------------------------
5)#include<stdio.h>
int main()
{
int x=10,y=4;
float z;
z=(float)x/y; //explicit conversion by programmer
printf("x=%d,y=%d,z=%f\n",x,y,z);
return 0;
}

./a.out
x=10,y=4,z=2.500000
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int x=10,y=4;
float z;
z=x/(float)y; //for y as explicit float it has the same output
printf("x=%d,y=%d,z=%f\n",x,y,z);
return 0;
}

./a.out
x=10,y=4,z=2.500000

-----------------------------------------------------------------------------------

char x=12,y=20,z; //one byte data type


z=x+y; //int/int

internally character is always converted into integer

char x=12;
short int y=20.x;
z=x+y; //char+int ==>int

LR+HR-->LR CONVERTED TO HR
13

#include<stdio.h>
int main()
{
char x=12,y=20,z;
printf("z=%zu\n",sizeof(x+y));
return 0;
}
./a.out
z=4 //size
-----------------------------------------------------------------------------------
Type promotion (DEPENDS ON LHS)

LHS type is HR and RHS type is LR → int = char → LR is promoted
to HR while assigning

Type demotion

LHS is LR and RHS is HR → int = float → HR rank will be demoted
to LR. Truncated
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int num=0;
num=num++ + ++num +num++;
num=num++; //undefined output
printf("%d",num);
}

./a.out
4

-----------------------------------------------------------------------------------

COMPILER OPTIMISATION

#include<stdio.h>
int main()
{
int num1=1, num2=0;
if (++num1 || num2++) // if ++num1 is true it wont go to num2++
{
printf(“num1 is %d num2 is %d\n”, num1, num2);
}
num1 = 1, num2 = 0;

else
{
printf(“num1 is %d num2 is %d\n”, num1, num2);
}
return 0;
}

output:
num1 is 2 num2 is 0
-----------------------------------------------------------------------------------
14

#include<stdio.h>
int main()
{
int num1=1, num2=0;
if (num1++ || ++num2) // if ++num1 is true it wont go to num2++
{
printf(“num1 is %d num2 is %d\n”, num1, num2);
}
num1 = 1, num2 = 0;

else
{
printf(“num1 is %d num2 is %d\n”, num1, num2);
}
return 0;
}

output:
num1 is 2 num2 is 0
-----------------------------------------------------------------------------------

#include<stdio.h>
int main()
{
int num1=0, num2=1;
if (num1++ || ++num2)
{
printf(“num1 is %d num2 is %d\n”, num1, num2);
}
num1 = 1, num2 = 0;

else
{
printf(“num1 is %d num2 is %d\n”, num1, num2);
}
return 0;
}

output:
num1 is 1 num2 is 2
-----------------------------------------------------------------------------------
15

JUNE 3
#include<stdio.h>
int main()
{
float num=0.7;
if(num == 0.7)
printf("equal");
else
printf("not equal");
return 0;
}

./a.out
not equal //as 0.7 is a non ending number

in if loop the number is considered as double in the system

for float
23
Sign 0/1 Exponent -0111 1110 Mantisa –
0110011001100...011
Mantisa is never ending
for 0.7

for double
52
Sign 0/1 Exponent – 01111111110 01100110011001100.........
00110

-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
float num=0.5;
if(num == 0.5)
printf("equal");
else
printf("not equal");
return 0;
}

/a.out
equal //as 0.5 has same value in float and double conversion
-----------------------------------------------------------------------------------

Compound statement
+=, -=, *=, /=, >>=, <<=.................
var=var+value

-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int num1 = 1, num2 = 1;
float num3 = 1.7, num4 = 1.5;
16

num1 += num2 += num3 += num4; //num3+=num4 =3.2 ==> num2 += 3.2==> 4.2 which
is demoted to 4 as num2 is an integer, num1
+= 4 ==>5
printf(“num1 is %d\n”, num1);
return ;
}

-----------------------------------------------------------------------------------

#include<stdio/.h>
int main()
{
float num=1;
if(num1=1) // it checks the value 1 assigned to num1, so if
executes
{
printf(“it is equal\n”);
}
else
{
printf(“not equal\n”);
}
return 0;
}

output:
it is equal
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
float num=0.5;
if(num =0 )
printf("equal");
else
printf("not equal\n");

printf("%f",num);
return 0;
}

./a.out
not equal
0.000000 //it executes the operation in if loop
-----------------------------------------------------------------------------------
BITWISE OPERATORS

&, | ,^ ,~ ,<< , >>

char x=25 //integer


char x=065 //octal
char x=0x58 //hexa-decimal
-----------------------------------------------------------------------------------
char x=0x61 ,y=0x13

since char 8bit is used for evaluation (incase of int we should use 32bit )
x & y ==>1
17

x= 0x61 ==> 0110 0001


y= 0x13 ==> 0001 0011
-------------------------------
&=0x01 ==> 0000 0001

x=0xAA y=0x57
x & y:
x=0xAA ==> 1010 1010
y=0x57 ==> 0101 0111
----------------------------------------
&=0x02 ==> 0000 001
----------------------------------------
-----------------------------------------------------------------------------------

x | y ==>1

x= 0x61 ==> 0110 0001


y= 0x13 ==> 0001 0011
-------------------------------
&=0x73 ==> 0111 0011 ==>115(decimal)
-------------------------------
-----------------------------------------------------------------------------------

XOR ==>if the inputs are same, then output will be 0, else it is
true.
input1 input2 output
0 0 0
0 1 1
1 0 1
1 1 0

char x=0xBC y=0x35

x=0xBC==> 1011 1100


y=0x35 ==> 0011 0101
-------------------------------
| XOR 1000 1001 =>0x89 =>137
-------------------------------
-----------------------------------------------------------------------------------
BITWISE COMPLIMENT(~)
input output
0 1
1 0
-----------------------------------------------------------------------------------
1. Left shift <<
char a= 0x35 ==53

MSB LSB

-->for every left shift MSB will be lost and LSB will be filled with zero
18

0 0 1 1 0 1 0 1

<==BIT IS MOVED LEFT, RIGHT LSB IS ADDED WITH ZERO


0 1 1 0 1 0 1 0

==6A == 106

<==BIT IS MOVED LEFT, RIGHT LSB IS ADDED WITH ZERO

1 1 0 1 0 1 0 0

==D4 ==>212

when a left shift is done , result= value *(2^number_of_shift)


Hence, left shift is the effecient way of multiplying the number by 2 power values.
(2,4,8..)
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
char a=0x35;
printf(“%d\n”, a<<2);
return 0;
}
./a.out
140
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
char a=0x35;
printf("%d\n",a<<2);
}
./a.out
212 //input is given as hexa, and output is in decimal
-----------------------------------------------------------------------------------
Right shift – signed right shift and unsigned right shift
1.Unsigned right shift
unsigned char a=0x35;
a>>2

MSB LSB

-->for every right shift LSB will be lost and MSB will be filled with zero

0x35==53

0 0 1 1 0 1 0 1

BITS ARE MOVED RIGHT, LEFT MSB IS ADDED WITH ZERO==>


0 0 0 1 1 0 1 0

0x1A==26
19

BITS ARE MOVED RIGHT, LEFT MSB IS ADDED WITH ZERO==>

0 0 0 0 1 1 0 1

0xD==13

when a right shift is done, result =value/ (2^number_of_shift)


Hence, right shift is the effecient way of dividing the number of 2 power values
20

JULY 4
OPERATORS – BITWISE
1. Bitwise operators prform operations on bits
2. The operand type shall be integral
3. Return type is integral value

&- If one input is zero , then output is zero


| - If one input is one, then output is one
! - toggle the input
^ - if the inputs are 1 and 0 , the output is one (XOR)

SIGNED RIGHT SHIFT:

signed char ch=96;


ch >> 2;

0 1 1 0 0 0 0 0

After one shift:


0 0 1 1 0 0 0 0
MSB retains the same after right shift

After second shift:


0 0 0 1 1 0 0 0
MSB retains the same after right shift
-----------------------------------------------------------------------------------
signed char ch=-56
2’s complement of -56 should taken:
2’s complement== 0011 1000
1100 0111
1
-------------
1100 1000
-------------
1 1 0 0 1 0 0 0

After one shift:


1 1 1 0 0 1 0 0
MSB retains the same after right shift

system storing as:

1110 0100
0001 1011
1
----------------
0001 1100 ==> -28
----------------
After second shift:
1 1 1 1 0 0 1 0
MSB retains the same after right shift

system storing as:


1111 0010
21

0000 1101
1
--------------
0000 1110 ==>-14
--------------

-----------------------------------------------------------------------------------

NOTE: if signed left shift is done, the output will be undefined behaviour
no of shift – should be positive, if negative the output will be undefined
behaviour

Right operand – has to be within the range


eg.. char ->8
MSB LSB
7 6 5 4 3 2 1 0

shift can be vary from 0 to7

-----------------------------------------------------------------------------------

for int ==> 0 to 31

4. signed char ch=96;


ch<<4;

94* 2^4 = 1536 ==> exceeds the limit -128 to 128


undefined behaviour

-----------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
int count;
unsigned char iter = 0xFF;
for (count = 0; iter != 0; iter >>= 1)
{
if (iter & 01)
{
count++;
}
printf("iter is %d\n",iter);
}
printf("count is %d\n", count);

return 0;
}

./a.out
iter is 255
iter is 127
iter is 63
iter is 31
iter is 15
iter is 7
iter is 3
22

iter is 1
count is 8

-----------------------------------------------------------------------------------

#include <stdio.h>
int main()
{
int count;
unsigned char iter = 0xAA;
for (count = 0; iter != 0; iter >>= 1)
{
if (iter & 01) //if &01 not given, the count will be eight
{
count++;
}
printf("iter is %d\n",iter);
}
printf("count is %d\n", count);

return 0;
}
./a.out
iter is 170
iter is 85
iter is 42
iter is 21
iter is 10
iter is 5
iter is 2
iter is 1
count is 4
-----------------------------------------------------------------------------------

BITWISE-MASK
unprotecting required bits of register and perform operations like:
--set bit
--clear bit
--get bit
etc..,

set bit -4
value =0xAA
7 6 5 4 3 2 1 0
1 0 1 0 1 0 1 0

OR 2^4 (0001 0000) ==> 1 << 4

value | 1 << 4

1010 1010
0001 0000 (OR)
----------------
1011 1010
----------------
23

JUNE 5
Set n-bits from LSB

Generic mask==> mask=(1<<pos) -1 //easy way

consider value : 0xAA

set 3bits from LSB

0xAA=> 1010 1010


mask=> 0000 0111 ((1<<3)-1)
----------------------------------
& operation- 1010 1111
---------------------------------.

-----------------------------------------------------------------------------------

set 4bits from LSB

0xAA=> 1010 1010


mask=> 0000 1111 ((1<<4)-1)
---------------------------------
& operation- 1010 1111
---------------------------------

-----------------------------------------------------------------------------------

ANOTHER WAY OF CREATING MASK:


#include <stdio.h>
int main()
{
int mask =0,i;
int n=4;
for(i=0;i<n;i++)
{
mask=mask|(1<<i);
printf("%x\n",mask);
}
printf("final mask =%x\n",mask);
return 0;
}

./a.out
1
3
7
f
final mask =f
-----------------------------------------------------------------------------------

CLEAR BIT
GENERIC MASK ==> (~(1 << pos))

Whatever the bit may be, make it as 0

1)
value=0xAA
24

clear the bit at position 3

0xAA ==> 1010 1010


mask ==> 1111 0111 (~(1 << pos))
-------------------------------
& operation- 1010 0010
-------------------------------

2)
value=0xAA
clear the bit at position 1

0xAA ==> 1010 1010


mask ==> 1111 1101 (~(1 << pos))
-------------------------------
& operation- 1010 1000
-------------------------------
-----------------------------------------------------------------------------------

FOR TOGGLING XOR IS BEST (^)

GENERIC MASK ==> (1<<pos)

To toggle the bit at position 3


value=0xAA

0xAA ==> 1010 1010


mask ==> 0000 1000
--------------------------------
XOR op- 1010 0010
--------------------------------

To toggle the bit at position 2


value=0xAA

0xAA ==> 1010 1010


mask ==> 0000 0100
--------------------------------
XOR op- 1010 1110
--------------------------------
-----------------------------------------------------------------------------------
For int
#include <stdio.h>
int main()
{
unsigned int num=8;
int i;
for(i=31; i>=0 ;i--)
{
printf("%d",((num>>i)&01));
}
printf("\n");
return 0;
}

./a.out
25

00000000000000000000000000001000
-----------------------------------------------------------------------------------
For char
#include <stdio.h>
int main()
{
unsigned char num=8;
int i;
for(i=7; i>=0 ;i--)
{
printf("%d",((num>>i)&01));
}
printf("\n");
return 0;
}
./a.out
00001000

EXPLANATION: //same for int

8 = 0000 1000
8>>7 ==> 0000 0000 & 1 ==0
8>>6 ==> 0000 0000 & 1 ==0
8>>5 ==> 0000 0000 & 1 ==0
8>>4 ==> 0000 0000 & 1 ==0
8>>3 ==> 0000 0001 & 1 ==1
8>>2 ==> 0000 0000 & 1==0
8>>1 ==> 0000 0000 & 1==0
8>>0 ==> 0000 0000 & 1==0
-----------------------------------------------------------------------------------

NIBBLE NUMBER:

TO SWAP THE NIBBLE:

unsigned char value=0xAB //for doing program


output=0xBA

to get 0x0B => 1010 1011


0000 1111 <=0x0F
------------
& 0000 1011 <=0x0B
------------

to get 0x0A => 1010 1011


1111 0000 <=0xF0
-------------
& 1010 0000 <=0xA0
-------------

result= ((value & 0x0F)<<4) | ((value & 0xF0)>>4)

-----------------------------------------------------------------------------------
26

JUNE 7
TERNARY OPERATOR:-- 3 Operators

Syntax : Condition? Expression 1 :Expression 2

res= num1>num2 ? num1: num 2;

num1 > num2 ? res=num1 : res=num2;

num1 > num2 ? printf(num1) : printf(num2);

-----------------------------------------------------------------------------------
RESULT CAN BE ANOTHER TERNARY OPERATION:
eg.:
condition ? (Condition ? Expr1 : Expr 2): expr2;

Greatest of 3 numbers:
num1>num2? (num1 > num3 ? Num2 :num3 ) :(num 2 > num3 ? num2 : num3);

j = 1 ? 2 && 3 : 4 ? 5 % 6 : 7 : 8 ;

j=1 ? 1 ? (2 && 3 ): 4 ? (5 %6) : 7 : 8 ==> 1 ? 1 ? 1 : 4 ? 5 : 7 : 8

Associativity = R to L

1 ? (1 ? (1 : (4 ? 5 : 7 )): 8 ==> ans : 1

-----------------------------------------------------------------------------------
COMMA OPERATOR( , ): Associativity : L to R (evaluate but not
execute)
--Separator and operator

int num1, num2; //separator

valid examples as operator:

1) num1 =( 1 , 2 , 3); // only the last operand will be returned


: num1=3
2) num1 =(num1++,2,3);
3) num1= (num1=num1+num2 , 2 , 2 );

num1=8;
num1=(num1+2, 3, 5) //num1=5, rest are discarded
-----------------------------------------------------------------------------------
int i=0 ,j=0;
j= i++ ? i++ : ++i ;
printf(“i=%d,j=%d\n”,i,j);

output : i =2 , j=2 // i ++? => false ==> ++i ==>i=2, j=false


condition

j= i++ ? i++ , j++ : ++j , i++ ;

j= (i++ ? (i++ , j++) : ++j ), i++ ; ==> (0++ ? (not taken) : taken ) ,
i++ /i=1 ,j=1
27

==> discarded, taken //j=i+


+

i=1 , j=2
-----------------------------------------------------------------------------------

for (i=0,j=0; i<5,j<10; i++,j++) //for (i=0,j=0; (i<5,j<10); (i+


+,j++))

i=10,j=10 // as i++,j++ post increment

-----------------------------------------------------------------------------------

int i=0;
char j=2;

printf(“ %zu \n” sizeof(i , j)); 1


printf(“ %zu \n” sizeof(j, i)); 4
printf(“ %zu \n” sizeof i , j)); 2 //j is taken (sizeof
i) , j
-----------------------------------------------------------------------------------

OVERFLOW AND UNDERFLOW :

--> data types have its range

if result range positve - overflow // for signed char-- above


+127=>overflow

if result range negative - underflow

Overflow result will be stored as follows:

signed char ch=127;


ch= ch +10; //result – (2 ^ n) => 137-256 == -119
ch= -119

for integer //result- (2 ^ 32)

Underflow result will be stored as follows:

signed char ch= -128;


ch= ch-1; //-128-1== -129
2’s complement is taken (or) otherwise can be written as result + (2^n)

129 => 1000 0001


0111 1110
1
------------
0111 1111 ==>127
------------

result = -129+256 = 127

-----------------------------------------------------------------------------------
28

JUNE 8
When you try to store the value higher than the storage value , it is overflow.

When you try to store the value lower than the storage value , it is underflow.

ARRAYS:

-Used to organise the data


-Collection of same data type

Static array - fixed size

Index - Position of the elements

Legal Access region - Within the size of the array (Outside that – illegal
access(no error))

Syntax:
data type array_name[size];

eg: int arr[5];


int arr[5]={10,20,30,40,50};

size of arr = size of datatype * size of array

Here, 4*5 = 20bytes


1000-1003 1004-1007 1008-1011 1012-1015 1016-1019
10 20 30 40 50
Base address:
1000

Arrays are always accessed through index value.

arr[0]=10
arr[1]=20
arr[2]=30
arr[3]=40
arr[4]=50

if given arr[5] the address 1020 is taken into account => illegal
access./a.out
-----------------------------------------------------------------------------------
Static array:
Program:
#include <stdio.h>
int main()
{
int arr[5]={10,20,30,40,50};
printf("Array elements are\n:");
for(int index=0;index<5;index++)
{
printf("%d\n",arr[index]);
}
return 0;
}
Array elements are
29

:10
20
30
40
50

-----------------------------------------------------------------------------------
Input from user:
#include <stdio.h>
int main()
{
int arr[5];
printf("ENTER 5 ELEMENTS:\n");
for(int index=0;index<5;index++)
{
scanf("%d",&arr[index]);
}
return 0;
}
/*
./a.out
ENTER 5 ELEMENTS:
5
4
3
2
1

./a.out
ENTER 5 ELEMENTS:
20 30 40 50 60
*/
-----------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
int arr[5];
printf("ENTER 5 ELEMENTS:\n");
for(int index=0;index<5;index++)
{
scanf("%d",&arr[index]);
}
printf("THE ARRAY ELEMENTS ARE:\n");
for(int index=0;index<5;index++)
{
printf("%d\n",arr[index]);
}

return 0;
}

/*
./a.out
ENTER 5 ELEMENTS:
5 4 7 5 5 6 5 4
THE ARRAY ELEMENTS ARE:
5
30

4
7
5
5 //only the positional values are taken, rest are discarded

./a.out
ENTER 5 ELEMENTS:
5
4
sdf //Stop the loop
THE ARRAY ELEMENTS ARE:
5
4
1871548608 //garbage values
22091
89480448

-----------------------------------------------------------------------------------
WAYS OF DECLARATION:

1.int arr[5]={10,20,30,40,50};

[0] [1] [2] [3] [4]


10 20 30 40 50

2. Partial initialisation:

int arr[5]={10,20};

[0] [1] [2] [3] [4]


10 20 0 0 0

3.Size can be skipped:

int arr[]={10,20,30,40};
[0] [1] [2] [3]
10 20 30 40

4. int arr[]; ==>error (atleast either allocation or size initialisation


should be done)

5. int arr[]={10,20,30, ,40}; //error ,space should not be given

6. int arr[5]; //values will be garbage value (when no element input are
taken)

7.length of array can be taken from user (normal scanf for “n” )
-----------------------------------------------------------------------------------

PROGRAM TO REVERSE THE ARRAY


#include <stdio.h>
int main()
{
31

int n,temp;
printf("enter the size of array\n");
scanf(" %d",&n);
int arr[n];
printf("enter the %d elements\n:",n);
for(int i=0;i<n;i++)
{
scanf("%d",&arr[i]);
}
for(int i=0,j=(n-1);i<j;i++,j--)
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
for(int i=0;i<n;i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
}

./a.out
enter the size of array
5
enter the 5 elements
:1 2 5 4 7
7 4 5 2 1
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int array1[5]={1,2,3,4,5};
int array2[5]={1,2};
int array3[]={2,3};
//int array4[]=*invalid*

printf("%zu\n",sizeof (array1));
printf("%zu\n",sizeof (array2));
printf("%zu\n",sizeof (array3));
}

./a.out
20
20
8
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int arr[5]={10,30,20,8,6},sum=0;
int index;
float avg;
for(index=0;index<5;index++)
{
sum=sum+arr[index];
}
32

avg=(float)sum/5;
printf("average =%f\n",avg);
}

./a.out
average =14.800000

//to print 2 decimal point printf(“%.2f”,value);


//to discard the zeros printf(%g”,value);
-----------------------------------------------------------------------------------
REVERSE THE ARRAY:

#include<stdio.h>
int main()
{
int arr[5]={10,30,20,8,6},temp;
for(int i=0,j=4;i<j;i++,j--)
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=arr[i];
}
for(int index=0;index<5;index++)
{
printf("%d ",arr[index]);
}
printf("\n");
}

./a.out
6 8 20 8 6
-----------------------------------------------------------------------------------
33

JUNE 9
Bubble sort:
-->Arrange the array in ascending order
int arr[5]={5,4,3,2,1};
#include<stdio.h>
int main()
{
int size=5;
int arr[5]={10,30,20,8,6},temp;
for(int i=0;i<size-1;i++)
{
for(int j=0;j<size-1-i;j++)
{
if(arr[j]>arr[j+1])
{
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
for(int i=0;i<size;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}

./a.out
6 8 10 20 30
-----------------------------------------------------------------------------------
CLOCK WISE ROTATION:

#include<stdio.h>
int main()
{
int size=5,i;
int arr[5]={10,30,20,8,6};
int temp=arr[0];
for(i=0;i<size-1;i++)
{
arr[i]=arr[i+1];
}
arr[i]=temp;
for(int i=0;i<size;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}

./a.out
30 20 8 6 10
-----------------------------------------------------------------------------------
34

#include<stdio.h>
int main()
{
for(int i=0;i<4;i++)
{
if(i>=3)
{
continue; //skips everything after it and go to next looping
action
}
printf("%d ",i);

for (int i=0;i<1;i++)


{
printf("hi ");
}
}
}
./a.out
0 hi 1 hi 2 hi
-----------------------------------------------------------------------------------
FUNCTIONS:
In programming languages it can be something which performs a specific
service.
-Take input
-Perform operation
-Generate output
-Reusable

Bitwise operators --> low level

Functions--> High level programming -> near to users

A Group of statements that perform specific tasks

How to write the function?


It involves 3 things:
1.Function declaration(Instruction to compiler about input and output)
Syntax:
return_datatype function_name(arg_type1,arg_type2,...n);

2.Funtion definition
3. Function call
-----------------------------------------------------------------------------------
#include<stdio.h>
int add(int a,int b);
int main()
{
printf("%d",add(5.5,2.2)); //truncate to int in function
}
int add(int a, int b)
{
return(a+b);
}
35

./a.out
7
-----------------------------------------------------------------------------------
36

JUNE 10
Re usability
– Functions can be stored in library & re-used
– When some specific code is to be used more than once, at different places,
functions avoids repetition of the code.

Divide & Conquer


A big & difficult problem can be divided into smaller sub-problems and solved
using divide & conquer technique

● Modularity can be achieved.


● Code can be easily understandable & modifiable.
● Functions are easy to debug & test.

One can suppress, how the task is done inside the function, which is called
Abstraction

BUG--> Faulty output.


Abstraction--> Hiding the implementation part
-----------------------------------------------------------------------------------

#include<stdio.h>
int foo(int x);
int main()
{
int x,y;
x=2;
y=foo(x);
printf("%d\n",y);
}
int foo(int x)
{
return(x=x+1);
}

./a.out
3
-----------------------------------------------------------------------------------
NO STORAGE OF RETURN VALUE
#include<stdio.h>
int foo(int x);
int main()
{
int x,y;
x=2;
foo(x); //it is not mandatory to collect the return
printf("%d\n",y); //garbage is printed
}
int foo(int x)
{
return(x=x+1);
}
./a.out
0
-----------------------------------------------------------------------------------
37

VOID FUNCTION

#include<stdio.h>
void foo(int x); //no return type
int main()
{
int x,y;
x=2;
foo(x); //it is not mandatory to collect the return
printf("%d\n",y); //garbage is printed
}
void foo(int x)
{
return(x=x+1); //warning will be there
}
-----------------------------------------------------------------------------------
ACTUAL AND FORMAL ARGUMENTS:
#include<stdio.h>
int foo(int x);
int main()
{
int x,y;
x=2;
y=foo(x); //x--> actual argument
printf("%d",y);
}
int foo(int a) //a-->formal argument
{
return(a=a+1);
}
-----------------------------------------------------------------------------------
FUNCTION AND THE STACK
1.Text segment – Bottom segment with executable code.
2.Stack Segment
3.Data Segment – Static, global
4.Heap -- Dynamic memory allocation -->allocated at run time
38

Stack—Grow downwards
Hole
39

Heap—Grow upwards

--whenever you call a function a stack memory will be allocated, pointer will be
linked to function.

--Whenever a new things are added in the stack memory will grow

--Whenever heap and stack pointer meet at a single memroy location-- memory is
exhausted..

Stack frame: whenever function is called it is created // main is also a function

1.Local variables : Variables declared inside function


2. Return address : to comeback to the same location in the main function
3.Parameter List : Arguments in the functions

At the end of the function , or at the return , the stack created for the function
will be discared, and memory will be cleared.
40

JUNE 11
If function definition is written before the main , then there is no need for
function declaration.

But it is good practice to write the function declaration.

Pass by value only returns one value

Pass by reference : pointers


-----------------------------------------------------------------------------------
#include<stdio.h>
int modify(int num1,int num2)
{
num1++;
num2++;
return num1; //exit the function
return num2; //dont execute this , as in above line the function exits
}
int main()
{
int x=10,y=10;
printf("Before Modificaton: x=%d ,y=%d\n",x,y);
x,y=modify(x,y); //stored in y
printf("After Modificaton: x=%d ,y=%d\n",x,y);
return 0;
}
./a.out
Before Modificaton: x=10 ,y=10
After Modificaton: x=10 ,y=11
-----------------------------------------------------------------------------------
TYPES OF FUNCTIONS:

1.Function without arguments and without a return


void-nothing
void func_name(void) //0 arguments

-----------------------------------------------------------------------------------
41

#include<stdio.h>
void func(void);
int main()
{
int x=0,y;
y=func(); //error to store the output
printf("%d\n",y);
return 0;
}
void func(void)
{
printf("hi everyone\n");
return 1; //warning
}

-----------------------------------------------------------------------------------

2.FUNCTION WITH ARGUMENTS AND WITHOUT A RETURN:

void func(int x);


-----------------------------------------------------------------------------------

3.FUNCTION WITHOUT ARGUMENTS AND WITH RETURN TYPE:

int func(void);
y=func();
int func()
{return; //it returns garbage
}
-----------------------------------------------------------------------------------
42

PROGRAM OPTIMISATION:

#include<stdio.h>
int even_odd(int num);
int main()
{
int num;
printf("ENTER A NUMBER: ");
scanf("%d",&num);
even_odd(num) ? printf("%d is even number\n",num):printf("%d is odd number\
n",num);
return 0;
}
int even_odd(int num)
{
return num%2;
}

-----------------------------------------------------------------------------------
43

JUNE 14
POINTERS-WHY?
address
1.To have C as a low level language being a high level language.
2. Returning more than one value from a funcion.
3.Pass by reference in function.
4.To have the dynamic allocation mechanism.

THE RULES OF POINTERS:

1. Pointer is an integer.
2. Referencing and De - referencing
3. Pointing means containing
4. Pointer type
5. Pointer Arithmetic
6. Pointing to Nothing
7. Static vs Dynamic Allocation
-----------------------------------------------------------------------------------
syntax:
data_type *pointer_name;
int *ptr;
char *cptr;
double *dptr;
1. POINTER IS AN INTEGER
int num; //(4 bytes) - compiler implementation dependent - for interview
char ch; //store value
But in case of pointers, it always stores the address of the variable
ADDRESS ARE ALWAYS IN INTEGERS - ( decimal, octal, hexadecimal, binary)
What we put in data bus in integer
What we put in address bus is pointer

-----------------------------------------------------------------------------------

#include<stdio.h>
int main() x
{
int x; //garbage at initialisation garbage
int *ptr; //garbage value *ptr
return 0;
}
garbage
If you don’t assign value to pointer, it remains a garbage value
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int x; //garbage at initialisation
int *ptr; //garbage value
printf("%zu",sizeof(*ptr));
return 0;
}
Size of printer:
==>32/64 – bitness
==>32 bit system pointer size will be 4 bytes irrespective of data type
==>64 bit system- 8bytes
-----------------------------------------------------------------------------------
44

RULE 2: REFERENCING AND DEREFERENCING:


*,& => user defined data type
&- 2 operand means bitwise operator
&- with one operand-> it will always give the address
* ->Deferencing operator -> give you the value
CONSIDER X=5, WHERE THE ADDRESS OF X IS 1000
int x=5;
&x ==>go to memory address of x-1000

int *ptr ptr


1000
Address-2000
ptr=&x;
*ptr==>1000=>5

Prefix
‘address of
operator’
(&) with
variable (x)
to get its
address and
store in the
pointer. ==>ptr=&number
Prefix ‘indirection operation’ (*) with pointer to get the value of variable(x) it
is pointing to. ==>*ptr
TO PRINT THE MEMORY IN HEXA-DECIMAL FORMAT ==>%p
-----------------------------------------------------------------------------------

#include<stdio.h>
int main()
{
int num=10;
int *ptr=&num;
printf("num= :%d\n",num);
printf("*ptr contains :%d\n",*ptr);
*ptr=100;
num=500;
printf("\nAfter assigning num=500, num= :%d\n",num);
printf("*ptr contains :%d\n",*ptr); //*ptr always gives the value of
present num
return 0;
}

./a.out
45

num= :10
*ptr contains :10

After assigning num=500, num= :500


*ptr contains :500
-----------------------------------------------------------------------------------
RULE 3: Pointing means containing
-----------------------------------------------------------------------------------

RULE 4: POINTER TYPE


*ptr ==> 4 bytes
*cptr ==> 1 bytes //while fetching variable value, the address stored in the
pointer would always be 32/64 depending on the system.
If in case of character, int pointer is used then the result would be a random
value as there is no 4bytes of value for character, only one byte of value.
-----------------------------------------------------------------------------------
46

JUNE 15
TYPE 4:CONTINUATION
-how the data will be stored ==> endianess
-2 Types
1.Little endian system
2.Big endian system
-->Most of the system will follow little endian system
-->Only motorola will follow big endian system
-----------------------------------------------------------------------------------
1.LITTLE ENDIAN SYSTEM:
1. int val= 0x12345678;
--little endian system says least significant byte will be in lowest address.
4 BYTES
78 65 43 12
|1000 | 10001 |1002 |1003
1004|

fetching date – 78 56 43 12 -rearrange 12345678

2. int num=0x56789
4 BYTES
89 67 05 00
|1000 | 10001 |1002 |1003
1004|

-----------------------------------------------------------------------------------
2.BIG ENDIAN SYSTEM:
1. int val= 0x12345678;
4 BYTES
12 34 56 78
|1000 | 10001 |1002 |1003
1004|

2. int num=0x56789
4 BYTES
00 05 67 89
|1000 | 10001 |1002 |1003
1004|

int *ptr = &num;


char *cptr = &num;
while fetching *ptr will fetch 4 byte, and *cptr fetches 1 byte
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int num=0x12345678;
int *ptr=&num;
char *cptr=&num;
printf("Number contains :%d\n",num);
printf("*ptr contains :%d\n",*ptr);
printf("*cptr contains :%x\n",*cptr);
return 0;
47

}
./a.out
Number contains :305419896
*ptr contains :305419896
*cptr contains :78 //Least significant byte
-----------------------------------------------------------------------------------

TO CHECK THE SYSTEM IS LITTLE ENDIAN OR BIG ENDIAN SYSTEM:


#include<stdio.h>
int main()
{
int num=0x12345678;
char *cptr=&num;
if(*cptr ==0x78)
printf("Little endian system\n");
else
printf("Big endian system\n");

return 0;
}
./a.out
Little endian system
-----------------------------------------------------------------------------------

PASS BY VALUE:
#include<stdio.h>
void modify(int *,int*);
int main()
{
int num1=10,num2=20;
printf("Before Modification : num1=%d , num2=%d\n",num1,num2);
modify(&num1,&num2);
printf("After Modification : num1=%d , num2=%d\n",num1,num2);
return 0;
}
void modify(int *n1,int *n2)
{
*n1=*n1+1;
*n2=*n2+1;
}
./a.out
Before Modification : num1=10 , num2=20
After Modification : num1=11 , num2=21
-----------------------------------------------------------------------------------

RULE :5 POINTER ARITHMETIC


-->To store more than one value of same type in continuous memory
int arr={10,20,30,40,50};
[0] [1] [2] [3] [4]
10 20 30 40 50
|1000 |1004 |1008 |1012 |1016-1019

arr= base address of array //here, arr=1000


int *ptr;
ptr=arr; //ptr=1000
48

#include<stdio.h>
void modify(int *,int*);
int main()
{
int arr={10,20,30,40,50};
int *ptr;
ptr=arr;
printf("%p\n",arr); //%p - address in hexa
printf("%p\n",ptr);
}
./a.out
0xa
0xa
-----------------------------------------------------------------------------------
49

JUNE 16
RULE 5: POINTER ARITHMETIC
#include<stdio.h>
int main()
{
int arr[5]={10,20,30,40,50};
int *ptr;
ptr=arr; //no need for ptr=&arr
printf("arr contains :%p\n",arr);
printf("ptr contains: %p\n",ptr);
printf("ptr base address value= %d\n",*ptr);
}
./a.out
arr contains :0x7fffe30abc60
ptr contains: 0x7fffe30abc60
ptr base address value= 10
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{ int arr[5]={10,20,30,40,50};
int *ptr;
ptr=arr;
ptr++; (ptr + (1*size of pointer data_type))
printf("arr contains :%p\n",arr);
printf("ptr contains: %p\n",ptr);
printf("ptr base address value= %d\n",*ptr);
}
./a.out
arr contains :0x7fffe30abc60
ptr contains: 0x7fffe30abc64
ptr base address value= 20
-----------------------------------------------------------------------------------
char *cptr; ==>address=1000 cptr++ ==>address=1001
double *dptr; ==>address=1000 dptr++ ==>address=1008
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int arr[5]={10,20,30,40,50};
int *ptr;
ptr=arr; //no need for ptr=&arr
for(int i=0;i<5;i++)
{
printf("ptr base address value= %d\n",*ptr+i);
}
}
./a.out
ptr base address value= 10
ptr base address value= 11
ptr base address value= 12
ptr base address value= 13
ptr base address value= 14
-----------------------------------------------------------------------------------
WAYS OF POINTING THE NEXT ELEMENTS:
1. *ptr++
2. *(ptr+iter)
3. ptr++
50

-----------------------------------------------------------------------------------

1. arr[i] <==> *(arr+i)


2. *(ptr+i) <==> ptr[i]

arr[i] == *(arr+i) == ptr[i] == *(ptr+i)


-----------------------------------------------------------------------------------
Alsways assign ptr=arr
a+b = b+a ==> commutative rule
*(arr+i) == *(i+arr) ==> arr[i] == i[arr]
*(ptr+i) == *(i+ptr) ==> ptr[i] == i[ptr]

sizeof(arr) ==> total size of array


&arr ==> gives total array
-----------------------------------------------------------------------------------
#include<stdio.h>
void print_array(int array[5]);
int main()
{
int arr[5]={10,20,30,40,50};
print_array(arr);
return 0;
}
void print_array(int array[5])
{
for(int iter=0;iter<5;iter++)
{
printf("%d\n",array[iter]);
}
}

./a.out
10
20
30
40
50
-----------------------------------------------------------------------------------
PROGRAM: OUTPUT:
#include<stdio.h> ./a.out
int main() x=5
{ ptr=0x7ffc8d4bc60c
int x=5; *ptr=5
int *ptr=&x;
printf("x=%d\n",x); x=6
printf("ptr=%p\n",ptr); ptr=0x7ffc8d4bc60c
printf("*ptr=%d\n",*ptr); *ptr=6

(*ptr)++; //x value is increased


and *ptr is increade

printf("x=%d\n",x);
printf("ptr=%p\n",ptr);
printf("*ptr=%d\n",*ptr);

}
51

#include<stdio.h> ./a.out
int main() x=5
{ ptr=0x7ffdd0394bec
int x=5; *ptr=5
int *ptr=&x;
printf("x=%d\n",x); x=6
printf("ptr=%p\n",ptr); ptr=0x7ffdd0394bec
printf("*ptr=%d\n",*ptr); *ptr=6

++*ptr; //x and //NOTHING CHANGES WITH THE PREVIOUS


*ptr value is incread OUTPUT

printf("x=%d\n",x);
printf("ptr=%p\n",ptr);
printf("*ptr=%d\n",*ptr);

#include<stdio.h> ./a.out
int main() x=5
{ ptr=0x7ffc85030acc
int x=5; *ptr=5
int *ptr=&x;
printf("x=%d\n",x); x=5
printf("ptr=%p\n",ptr); ptr=0x7ffc85030ad0
printf("*ptr=%d\n",*ptr); *ptr=-2063398192

*++ptr; //ptr and


*ptr value is increased

printf("x=%d\n",x);
printf("ptr=%p\n",ptr);
printf("*ptr=%d\n",*ptr);
//garbage value

}
#include<stdio.h> ./a.out
int main() x=5
{ ptr=0x7ffe3a621cdc
int x=5; *ptr=5
int *ptr=&x;
printf("x=%d\n",x); x=6
printf("ptr=%p\n",ptr); ptr=0x7ffe3a621cdc
printf("*ptr=%d\n",*ptr); *ptr=6

++(*ptr); //x value


and *ptr value is increased

printf("x=%d\n",x);
printf("ptr=%p\n",ptr);
printf("*ptr=%d\n",*ptr);
52

//garbage value

}
53

JUNE 17
FUNCTION PROTOTYPE IS SIGNATURE OF FUNCTION SPECIFYING:
-Number of function paramters abd their types
-return type of function.
RETURNING AN ARRAY:
return_type *func_name(data_type *arg, size)
{
//logical
return base_address_array;
}
-----------------------------------------------------------------------------------
#include<stdio.h>
int *modify_array(int *array, int size);
void print_array(int array[], int size);
int main()
{
int array[5]={10,20,30,40,50};
int *new_array_val;
new_array_val=modify_array(array,5);
print_array(new_array_val, 5);
return 0;
}

int *modify_array(int *array, int size)


{
int iter;
for(iter=0 ; iter <size;iter++)
{
*(array+iter)+=10;
}
return array;
}
void print_array(int array[], int size)
{
for(int iter=0; iter<size; iter++)
{
printf("Index %d has Element %d \n",iter,array[iter]);
}
}

./a.out
Index 0 has Element 20
Index 1 has Element 30
Index 2 has Element 40
Index 3 has Element 50
Index 4 has Element 60
-----------------------------------------------------------------------------------
#include<stdio.h>
int return_array(void);
int main()
{
int array[5]={10,20,30,40,50};
int *new_array;
new_array=return_array();
return 0;
}
54

int return_array(void)
{
int array[5]={50,60,70,80,90};
return array; //returning local variable is not allowed , it wil
show warning
} //or error
-----------------------------------------------------------------------------------
IN STATIC VARIABLE, Static variable memory will be allocated in data segment not in
the stack segment. By default the value will be zero.
Static int a; //by default, value will be 0

main() function()
Local variable Local variable
Return value-OS Return value-main ()address
Parameter list Parameter list

Static variable/data segment memory will available until the application is


terminated main().
#include<stdio.h>
int* func_return(void);
int main()
{
int *ptr;
ptr=func_return();
printf("%d",*ptr); //15 will be printed
}
int* func_return(void)
{
static int a=15;
return &a;
}
./a.out
15
-----------------------------------------------------------------------------------
#include<stdio.h>
int func(void);
int main()
{
func();
func();
}
int func(void)
{
static int a=15;
printf("%d\n",a);
a++;
}
./a.out
15
16 //static variable in initialised only once in an execution and
value will not be gone until the end of the main function.
-----------------------------------------------------------------------------------
RECURSIVE FUNCTION:
-Identifying the base case (termination condition)
function will be infinite and some point it will be terminated abnormally.
55

- How to call the function again – where to call the function


inside the same function and call the function.

TO FIND THE FACTORIAL:


#include<stdio.h>
int factorial(int num);
int main()
{
int num=3;
int output=factorial(num);
printf("%d\n",output);
return 0;
}
int factorial(int num)
{
if(num<=1) //end condition.
return num;
num= num*factorial(num-1); //calling the function
}
./a.out
6
-----------------------------------------------------------------------------------

MAIN() CAN BE A CALLED AS RECURSIVE FUNCTION, NOT A TRUE RECURSIVE FUNCTION,


BECAUSE IN CASE OF RECURSIVE, FUNCTION ALWAYS TAKE A VALUE(ARGUMENT)
56

JUNE 21
TYPES OF I/O:

1. FORAMATTED I/O
2. UNFORMATTED I/O
3. BUFFER

BUFFER(Stream)- Space or memory allocated for each operation, and a pointer is


always allocated to it.

There is a stream for input, output, and error.


File descriptors
1.STDIN -Standard Input steam 0
2.STDOUT -Standard Output Steam 1
3.STDERR -Standard Error stream 2

-----------------------------------------------------------------------------------
THE HEADER FILE:

#include<stdio.h>
• When the reference is made with “<name>” the search for the files happen in
standard path.
• Header file Vs Library

HOW TO USE HEADER FILE


• <> - angular brackets- in built header file – stdio.h, string.h,math.h
• Search the header file in the standard path

• “ “ - user defined header files.


(compiler will first search them in the same working directory
else it will go and search in the standard path
if both doesn’t have the header file it will throw the error)

-----------------------------------------------------------------------------------

UNFORMATTED I/O:

a --> a (not sure) (not ascii character)


• Unformatted I/O is not directly human readable, so you cannot type it out on
a terminal screen or edit in text editor.

• getchar() and putchar() are functions part of standard C library.

• Conio.h has functions like getch() getche(), putch(), not supported in linux
and unix systems.

-----------------------------------------------------------------------------------

#include<stdio.h>
int main()
{
char ch;
for(;(ch=getchar()) != '9';)
{
putchar(ch); //putchar(toupper(ch)); TO UPPER CASE
57

}
}
./a.out
2
2
5
5
h
h
A
A
9

-----------------------------------------------------------------------------------

GETCHAR() & PUTCHAR()


#include<stdio.h>
#include<ctype.h>
int main()
{
char ch;
for(;(ch=getchar()) != EOF;) //end of file ctrl+d
{
putchar(toupper(ch));
}
puts(“EOF RECEIVED”); //prints a strings
}
./a.out
5
5
2
2
EOF RECEIVED
-----------------------------------------------------------------------------------

GETC() AND PUTC():


#include<stdio.h>
#include<ctype.h>
#include<unistd.h> //mandatory for getc() & putc() in some versions.
{
char ch;
for(;(ch=getc(stdin)) != EOF;) //stdin and stdout must be mentioned
{
putc(toupper(ch),stdout);
}
puts("EOF RECEIVED\n");
}./a.out
25s6d
25S6D
EOF RECEIVED
-----------------------------------------------------------------------------------

stdout & stderr:

stderr

#include<stdio.h>
58

#include<ctype.h>
#include<unistd.h>
int main()
{
char ch;
while(1)
{
putc('A',stderr);
//unistd.h is mandatory for sleep
sleep(1); //display after a delay
}
}

./a.out
AAAAAAAAAAAAA^C

ch stderr

1000 //stderr got precedence,urgency


A
stdout

AAAAAAAAAAAAAAAAAA

-----------------------------------------------------------------------------------

stdout
#include<stdio.h>
#include<ctype.h>
#include<unistd.h>
int main()
{
char ch;
while(1)
{
putc('A',stdout);
//unistd.h is mandatory for sleep
sleep(1); //display after a delay
}
}
./a.out
^c
//nothing gets printed
59

stdout ch

1000
A
output buffer

AAAAAAAAAAAAAAAAAA
once the condition is false/EOF ,flush the buffer

stdout

Since there is no false condition or EOF the output buffer is never flushed to the
stdout
-----------------------------------------------------------------------------------

#include<stdio.h>
#include<unistd.h>

int main()
{
char str[10];
puts("ENTER THE STRING: ");
gets(str);
puts(str);
return 0;

}
./a.out
ENTER THE STRING:
sdfsgd
sdfsgd

./a.out
ENTER THE STRING:
sdfgsdfsdfshfg //given over 10 characters, thats why gets is
considered as dangerous
sdfgsdfsdfshfg
*** stack smashing detected ***: terminated
Aborted (core dumped)

fgets can be used instead


-----------------------------------------------------------------------------------
60

JUNE 22
STANDARD I/O – FORMATTED
• Data is formatted or transformed
• Converts the internal binary representation of the data to ASCII before being
stored.
• Expensive in terms of space and time
• eg.. printf() and scanf().

man 3 printf – to get functions in terminal.

int num;
scanf(“%d”,&num);
printf(“%d\n”,num);

stdin -as character


scanf

1 2 3 \n
Input buffer

1 2 3 \n (individual
scanfcharacter)
checks the format specifier

1000
123 printf - output buffer
printf
1 2 3 \n
stdout

123 (individual character)

#include<stdio.h>
int main()
{
char a[8]="EMERTXE";
printf(a); //throws a warning
}
./a.out
EMERTXE
VARIADIC FUNCTION

int printf(const char *ptr,...); //number of arguments are not fixed


--> can pass any number of arguments

a maximum of 127 arguments can be passed - based on research

printf()- type specifiers


61

printf() - type length specifiers

printf() - width

printf() - precision
62

printf() - flags

printf() - escape sequence


63
64

JUNE 23
Printf is a function that has int as return type

#include<stdio.h>
int main()
{
int ret;
char a[8]="EMERTXE";
ret=printf(a);
printf("\n%d\n",ret);
}
./a.out
EMERTXE
7
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int ret,num=10;
char string[]="EMERTXE";
ret=printf("%s\n%d\n",string,num); //counts \n as a character
printf("the printf() function printed %d characters\n",ret);
return 0;
}
./a.out
EMERTXE
10
the printf() function printed 11 characters
-----------------------------------------------------------------------------------

The printf prints the output through the output buffer, and it considers the output
as individual characters.

Sprintf() - similiar to printf() but prints to the buffer instead of stdout.

• Buffer (array,string) must be big enough to receive the result.

#include<stdio.h>
int main()
{
int num1=123;
char ch='A';
float num2=12.645;
char string1[]="sprintf() TEst";
char string2[100];
sprintf(string2,"%d %c %f %s\n",num1,ch,num2,string1);
printf("%s\n",string2);
}

./a.out
123 A 12.645000 sprintf() Test

-----------------------------------------------------------------------------------
65

#include<stdio.h>
int main()
{
int num1=123;
char ch='A';
float num2=12.645;
char string1[]="sprintf() TEst";
char string2[10];
//undefined behaviour because of low storage space
sprintf(string2,"%d %c %f %s\n",num1,ch,num2,string1);
printf("%s\n",string2);
}
./a.out
123 A 12.645000 45000 45000 45

*** stack smashing detected ***: terminated


Aborted (core dumped)

-----------------------------------------------------------------------------------

space.\n,\0 are considered as end of input

#include<stdio.h>
int main()
{
int num1;
char ch;
float num2;
char string1[20];
char string2[100];
scanf("%d %c %f %s",&num1,&ch,&num2,string1);
sprintf(string2,"%d %c %f %s\n",num1,ch,num2,string1);
printf("%s\n",string2);
}

./a.out
2 a 4.5 dfsg,.25
2 a 4.500000 dfsg,.25
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int num1;
char ch;
float num2;
char string1[20];
char string2[100];
scanf("%d %c %f %s",&num1,&ch,&num2,string1);
sprintf(string2,"%d %c %f %s\n",num1,ch,num2,string1);
printf("%s\n",string2);
}
66

./a.out
a 2 4.5 sdfg //a mismatch is detected in i/p buffer so it
terminates
0

/a.out
10.2 a hello world
10 . 2.000000 a // . is considered as a character

-----------------------------------------------------------------------------------

#include<stdio.h>
int main()
{
int num1;
char ch;
float num2;
char string1[20];
char string2[100];
scanf("%d %c %f %s",&num1,&ch,&num2,string1);
printf("%d %c %f %s\n",num1,ch,num2,string1);
scanf("%s",string2);
printf("%s\n",string2);
}

./a.out
10.2 a hello wolrd
10 . 2.000000 a // the buffer still has the value hello wolrd and
when hello scacnf is used again it flushes off the
remaining.

-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int hh,mm,ss;
printf("Enter time in format HH:MM:SS\n");
scanf("%d%*c%d%*c%d",&hh,&mm,&ss); //%*c to ignore the character
printf("%d:%d:%d\n",hh,mm,ss);
return 0;
}

./a.out
Enter time in format HH:MM:SS
13:25:52
13:25:52
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
char str[20];
scanf("%[a-z A-z]",str); //a-z,space,A-Z is taken for string
printf("%s",str);
return 0;
}
./a.out
hello i am karthi
67

hello i am karthi

scanf(“%[0-9]”,str); //can be used for number only inputs


-----------------------------------------------------------------------------------

#include<stdio.h>
int main()
{
int num=100,ret;
printf("Enter a number [is 100 now]: ");
ret=scanf("%d",&num); //scanf returns successful read values with
repect to specifiers
if(ret != 1)
{
printf("Invalid return %d,the number is still %d\n",ret,num);
return 1;
}
else
{
printf("Number is modified with %d\n",num);
}
return 0;
}
./a.out
Enter a number [is 100 now]: asdf
Invalid return 0,the number is still 100

./a.out
Enter a number [is 100 now]: 2
Number is modified with 2
-----------------------------------------------------------------------------------
PROTOTYPE:
int sscanf(const char *string, const char *format, ......);

sscanf() read from string or buffer instead of stdin

#include<stdio.h>
int main()
{
int age;
char array1[10];
char array2[10];
char array3[]="I AM 21 YEARS";
sscanf(array3,"%s %s %d",array1,array2,&age);
printf("YOU ARE %d YEARS OLD\n",age);
printf("%s\n%s\n",array1,array2);
return 0;
}

./a.out
YOU ARE 21 YEARS OLD
I
68

AM
-----------------------------------------------------------------------------------

UNFORAMTTED FOMATTED
1. NO FORMAT SPECIFIER 1. FORMAT SPECIFIERS ARE USED

2. DOES NOT ALLOWS TO SUPPLY INPUT OR 2. ALLOWS TO SUPPLY INPUT OR DELAY


DISPLAY OUTPUT OUTPUT IN USER DEFINED FORMAT

3. USER FRIENDLY
3. NOT USER FRIENDLY
4. ANY DATA TYPE
4. ONLY IN THE FORM OF CHARACTERS.

5. eg. Getchar(), putchar(), gets(), 5. printf(), sprintf(), scanf(),


puts(),getc() , putc(). sscanf().

6. NO CONVERSION, SIMPLE, LESS SPACE


AND TIME 6. COSTLY- SPACE AND TIME.

-----------------------------------------------------------------------------------
69

JUNE 24
BUFFERS – TEMPORARY STORAGE

If we dont have buffers, each characters will be performed in separate process.

Buffer- ways to be flushed

1. after filling the buffer size //1024 bytes


2. after successful termination of the program
3. by using “\n”
4. explicitly flushing by using fflush(stdout)
5. by using scanf
6. by setting the output buffer to null

setbuff(stdout,NULL); //disabling the output buffer


//behaves like stderr

-----------------------------------------------------------------------------------
1. after filling the buffer size
#include<stdio.h>
#include<unistd.h>
int main()
{
while(1)
{
printf("hello");
sleep(1);
}
return 0;
}
output doesnt print in the terminal, until the buffer is filled and flushed out.
1sec to 1 char
hello-5bytes time=1024bytes/5 =205seconds

so it takes 205seconds to print the one buffer output, and the while loop keeps
storing in the buffer.
-----------------------------------------------------------------------------------
2. after successful termination of the program
#include<stdio.h>
#include<unistd.h>
int main()
{

printf("hellohi_how aru_doing_jsjfkksdkfskndfsjdfkmnkfnskfnsk");
sleep(1);
return 0;
}

./a.out
hellohi_how aru_doing_jsjfkksdkfskndfsjdfkmnkfnskfnsk

-----------------------------------------------------------------------------------
70

3. by using “\n”

#include<stdio.h>
#include<unistd.h>
int main()
{
while(1)
{
printf("hello\n");
sleep(1);
}
return 0;
}
./a.out
hello
hello
hello
hello
^C
-----------------------------------------------------------------------------------
4.explicitly flushing using fflush(stdout)

#include<stdio.h>
#include<unistd.h>
int main()
{
while(1)
{
printf("hello\n");
fflush(stdout);
sleep(1);
}
return 0;
}
./a.out
hello
hello
hello
hello
^C
-----------------------------------------------------------------------------------
5. by using scanf()

#include<stdio.h>
#include<unistd.h>
int main()
{ int num;
while(1)
{
printf("hello\n");
scanf("%d",&num);
sleep(1);
}
return 0;
}
71

./a.out
hello
5
hello
5
hello
^C
-----------------------------------------------------------------------------------
6. by setting the output buffer to null

#include<stdio.h>
#include<unistd.h>
int main()
{ setbuf(stdout,NULL); //disable the output buffer, so stdout is used
directly
while(1) //behaves like stderr
{
printf("hello\n");
sleep(1);
}
return 0;
}
./a.out
hello
hello
hello
hello
hello
hello
^C
-----------------------------------------------------------------------------------

input buffer
1. to flush the input buffer- __fpurge(stdin); //#include<stdio_ext.h>

all function in #include<stdio_ext.h> starts with a double underscore “__”


-----------------------------------------------------------------------------------

2.getchar() and loop.

#include<stdio.h>
#include<unistd.h>
int main()
{
char ch;
printf("ENTER A STRING\n");
while(1)
{
scanf("%c",&ch);
while(getchar()!='\n');
printf("%c\n",ch);
}
return 0;
}

./a.out
ENTER A STRING
72

jdjfs
j
jsdkf
j
^C
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<unistd.h>
int main()
{
while(1)
{
fprintf(stdout,"hello");
fprintf(stderr,"world");
sleep(1);
}
return 0;
}
./a.out
worldworldworldworld^C
-----------------------------------------------------------------------------------
STORAGE CLASS – STATIC
--> static or register --> BSS – block started by symbol

#include<stdio.h>

int main()
{
int array[5]={1,2,3,4,5},i;
for(i=-1;i<sizeof(array)/sizeof(array[0]);i++)
{
printf("%d\n",array[i]);
}
return 0;
}

it never enters the for loop , as the sizeof() returns unsigned integer, and i=-1
is a signed integer so, -1 > sizeof() in binary format.

signed>unsigned

-1=11111111111111111111111111111111
-----------------------------------------------------------------------------------
73

JUNE 25
STRING

-->Sequence of character terminated with ‘\0’


-->array of character terminated with ‘\0’

• Continuous sequence of character


• Stores printable ASCII characters and extensions
• End of the string is marked with a special character, the null character
• ‘\0’ is implicit in strings enclosed with “ ”

#include<stdio.h>
int main()
{
//it is a character array not a string
char arr[5]={'h','e','l','l','o'}; //stored in stack memory 5 bytes
}
-----------------------------------------------------------------------------------
Ways to create a string

1. #include<stdio.h>
int main()
{
char arr[6]={'h','e','l','l','o','\0'}; //explicity adding ‘\0’
character at the end.
}

NOTE: space has to be incremented by 1


--> array of characters terminated with ‘\0’
-----------------------------------------------------------------------------------
2. char str[6]={‘h’,'e’,l','l','o','\0'};
char str[]={‘h’,'e','l','l','o','\0'};
-----------------------------------------------------------------------------------
3. char str[3]={“h”,”e”,”l”,”l”,”e”,”\0”}; //each character is considered as a
string
//invalid creation/initialization.
//possible only in two dimensional
arrays.
-----------------------------------------------------------------------------------
4.char str2[]={“h” ”e” “l” “l” “o” “\0”};
\\valid syntax- concatenation.
//compiler implicitly add a null character at the end.
//i.e h\0 + e\0 + l\0 + l\0 +o\0 +\0

hell\0 is stored
-----------------------------------------------------------------------------------
5. char str5[6]={“HELLO”}; //compiler implicitly add a ‘\0’ at the end
//written inside a “ “ is considered as a
string

char str[6]=”HELLO”; //valid


char str[]=”hello”; //valid
-----------------------------------------------------------------------------------

6. char *str9 = “Hello”; //pointer to an characters


74

//size of str9? 32Bit=4 64bit=8


//memory will be allocated in code segment
//this is a string literal

-----------------------------------------------------------------------------------

#include<stdio.h>
int main()
{
char arr[10]={'h','e','l','l','o'};
printf("%s\n",arr); //looks for \0 for end of the string sometimes
return 0;
}

hello //no problems this time

-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
char arr[10]={'h','e','l','l','o','\0'};
printf("%s\n",arr); //looks for '\0' for end of the string
sometimes
return 0;
}
hello
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
char arr[10]={"h","e","l","l","o","\0"};
printf("%s\n",arr); //looks for '\0' for end of the string
sometimes
return 0;
}
//compile time error showing excess elements
-----------------------------------------------------------------------------------
75

#include<stdio.h>
int main()
{
char arr[10]={"h""e""l""l""o""\0"};
printf("%s\n",arr);
return 0;
}
./a.out
hello //no error

-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
char str="hello"; //store in code segement and return base address
printf("%c\n",str);
return 0;
}
//null is printed

-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
char *str="hello"; //store in code segement and return base
address
printf("%s\n",str);
return 0;
}
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
char array1[5]={'H','E','L','L','O'}; //explicitly declared
char array2[]="Hello";
printf("%zu\n",sizeof(array1));
printf("%zu\n",sizeof(array2));
return 0;
}
./a.out
5
6
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
if(sizeof("HELLO" "WORLD")==sizeof("HELLO")+sizeof("WORLD"))
//11=6+6
printf("equal\n");
else
printf("not equal\n");
return 0;
76

}
not equal
-----------------------------------------------------------------------------------

char str[6]; //address assigned in user segment


str=”world”; //address assigned in code segment and returns the
address(literal)

str address allocated at initialisaiton

1000 1002 1003 1004 1005 1006

string literal allocated address is in the code segment and returns the base
address and to store it str should be a pointer.

Code segment
w o r l d \0
1000 1002 1003 1004 1005 1006.

code segement – string literals are constant and cannot be modified.

it gives a compile time error.


-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
char str1[6]="hello"; //valid
char str2[6]; //valid
char *str3="hello"; //valid
char *str4;
str4="world"; //valid
}
-----------------------------------------------------------------------------------
77

JUNE 28
STRING – SHARING

#include<stdio.h>
int main()
{
char *str1="Hello"; //string literals, address assigned in code segment
char *str2="Hello"; //same data assigned to str2 and there is no point
if(str1==str2) //in trying to give a new address
printf("THEY SHARE THE SAME SPACE\n");
else
printf("THEY SHARE DIFFERENT SPACE\n");
return 0;
}
./a.out
THEY SHARE THE SAME SPACE
code segement - constant
H e l l o
1000

str1
1000
str2
1000
code segment returns the same address to both
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
char *str1="hello"; //string literals, address assigned in code segment
char *str2="Hello"; //different address for different string even a
single char differ.
if(str1==str2)
printf("THEY SHARE THE SAME SPACE\n");
else
printf("THEY SHARE DIFFERENT SPACE\n");
return 0;
}
./a.out
THEY SHARE DIFFERENT SPACE

-----------------------------------------------------------------------------------

#include<stdio.h>
int main()
{
char str1[6]="Hello"; //both has ‘\0’ at end, stack memory
char *str2="Hello"; //both has ‘\0’ at end, code segment

if(str1==str2)
printf("THEY SHARE THE SAME SPACE\n");
else
printf("THEY SHARE DIFFERENT SPACE\n");
return 0;
}
78

./a.out
THEY SHARE DIFFERENT SPACE
-----------------------------------------------------------------------------------

#include<stdio.h>
#include<string.h>
int main()
{
char *str="Hello";
int ret;
ret=strlen(str);
printf("%d\n",ret);
return 0;
}

5
strlen() gives the number of character excluding ‘\0’

char *str[6]=”hello” --> cannot be initialised like this


error: invalid initializer

-----------------------------------------------------------------------------------

#include<stdio.h>
#include<string.h>
int main()
{
char *str="Hello";
int ret;
ret=strlen(str);
printf("%d\n",ret);
printf("%zu\n",sizeof(str));
return 0;
}
/a.out
5
8 //*str is a pointer
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<string.h>
int main()
{
char str[]="Hello";
int ret;
ret=strlen(str);
printf("%d\n",ret);
printf("%zu\n",sizeof(str)); //size of considers ‘\0’ for
counting
return 0;
}
./a.out
5
6
-----------------------------------------------------------------------------------
79

#include<stdio.h>
#include<string.h>
int main()
{
char str[]={'h','e','l','l','e','\0'};
int ret;
ret=strlen(str); //loop through string until it finds the ‘\0’
printf("%d\n",ret);
printf("%zu\n",sizeof(str));
return 0;
}
./a.out
5
6
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<string.h>
int main()
{
char str[]={'h','e','l','l','e'}; //may result in un-defined behaviour for
strlen
int ret; //since there is no ‘\0’ expilicitly given
ret=strlen(str);
printf("%d\n",ret);
printf("%zu\n",sizeof(str));
return 0;
}
5
5
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<stdio.h>
#include<string.h>
int main()
{
char *str= "hello";
int ret;
ret=strlen(str); //searches for ‘\0’ to terminate the string
printf("%d\n",ret);
printf("%zu\n",sizeof(*str));
return 0;
}
./a.out
5
1 //*str points to address of ‘h’
-----------------------------------------------------------------------------------

TO PRINT THE STRING

1. puts(string) - unformatted
2. %s - formatted
3. putchar(ch) - unformatted used with loop
80

4. passing as a function argument

#include<stdio.h>
#include<string.h>
int main()
{
char *str= "hello";
printf("%s\n",str); //2
puts(str); //1
while(*str) //3
{
putchar(*str);
str++;
}
return 0;
}
./a.out
hello
hello
hello
-----------------------------------------------------------------------------------
USING A FUNCTION:

#include<stdio.h>

void print(const char *str) //adding const is a standard, will not show
error
{
while(*str)
{
putchar(*str++);
}
}
int main()
{
char *str= "Hello World";
print(str);
return 0;
}
./a.out
Hello World
-----------------------------------------------------------------------------------
READING THE STRING
1. gets()
2. fgets()

#include<stdio.h>
#include<string.h>
int main()
{
char str[]= "Hello World";
gets(str); //not recommended, takes extra space to overwrite in
//unallocated area.
fgets(str,6,stdin); //takes in only specified length of characters
printf("THE STRING IS :%s\n",str);
return 0;
}
81

./a.out
sdfsfasdf
THE STRING IS :sdfsfasdf //for gets() , it overwrites

./a.out
sdfasdf
THE STRING IS :sdfas //for fgets(), takes only specified characters-1
-----------------------------------------------------------------------------------

SELECTIVE SCANF()

#include<stdio.h>
#include<string.h>
int main()
{
char str[50];
scanf("%5[^\n]",str); //take 5 characters, if ”^” not given it works as
gets().
printf("%s\n",str); //now it works as fgets()
return 0;
}
./a.out
dfsdfsdfdsfdsf
dfsdf

-----------------------------------------------------------------------------------
size_t --> typedef
unsigned long int --> 64 bit
unsigned int --> 32 bit

int strcmp(const char *str1, const char *str2)


<0 ==> str1<str2
>0 ==> str1>str2
=0 ==> str1=str2

char *strcpy (char *dest, const char *src)

char *strstr (const char *haystack. Const char *needle) ==>check string

char *strchr (const char *s, int c) ==>check character

char *strcat (char *dest , const char *src) ==> concant


-----------------------------------------------------------------------------------
82

JUNE 29
Gets() is considered because it invades the unallocated space.
On the other hand, fgets() gets only specified length of elements.

#include<stdio.h>
#include<string.h>
int main()
{
char *str; //cannot access this pointer, maybe used by other
applications
scanf("%5[^\n]",str);
printf("%s\n",str);
return 0;
}
./a.out
segmentation fault.

A pointer with no value assigned at time of initialisation, it would result in


segmentation fault, and wont be able to give input.

-----------------------------------------------------------------------------------
#include<stdio.h>
#include<string.h>
int main()
{
char src[20],dest[20];
printf("ENTER THE STRING: ");
scanf("%20[^\n]",src);
strcpy(dest,src);
printf("SOURCE STRING IS \n%s\n",src);
printf("DESTINATION STRINGS IS \n%s\n",dest);
return 0;
}
./a.out
ENTER THE STRING: hello how are you doing buddy,anything new?
SOURCE STRING IS
hello how are you do
DESTINATION STRINGS IS
hello how are you do

-----------------------------------------------------------------------------------

char *strcpy (char *dest, const char *src) ==> returning the address

#include<stdio.h>
#include<string.h>
int main()
{
char src[20],dest[20];
char *ret;
printf("ENTER THE STRING: ");
scanf("%20[^\n]",src);
ret=strcpy(dest,src); //strcpy will replace the contents
printf("SOURCE STRING IS \n%s\n",src);
printf("DESTINATION STRINGS IS \n%s\n",dest);
83

printf("RETURNED ADDRESS IS \n%s\n",ret);


return 0;
}

./a.out
ENTER THE STRING: hello dude,wasup dude, bye duuuuude...
SOURCE STRING IS
hello dude,wasup dud
DESTINATION STRINGS IS
hello dude,wasup dud
RETURNED ADDRESS IS
hello dude,wasup dud
make sure that always dest has equal or more space than the source string, else it
would result in runtime error.

with src[20], dest[10]

./a.out
ENTER THE STRING: sdfkjslkfjskjfksjfsdfdsf4
SOURCE STRING IS
skjfksjfsd
DESTINATION STRINGS IS
sdfkjslkfjskjfksjfsd //undefined behaviour
RETURNED ADDRESS IS
sdfkjslkfjskjfksjfsd

-----------------------------------------------------------------------------------
my_strcpy() function
#include<stdio.h>
void my_strcpy(char *dest,char *src);
int main()
{
char src[20],dest[20];
printf("ENTER THE STRING: ");
scanf("%20[^\n]",src);
my_strcpy(dest,src);
printf("SOURCE STRING IS %s\n",src);
printf("DESTINATION STRINGS IS %s\n",dest);
return 0;
}
void my_strcpy(char *dest, char *src)
{
while(*dest++ = *src++);
}

eg..
src
E M E R T X E \0 Gv Gv Gv Gv ... ... .. ... ... ... ... .... ... ....
.. . .
1001 -1008 9 10 11

dest
gv Gv Gv gv gv gv gv gv Gv Gv Gv Gv ... ... .. ... ... ... ... .... ... ....
.. . .
Gv-garbage value
84

each character is copied from src to dest until ‘\0’ character.

./a.out
ENTER THE STRING: hello how are you doing?
SOURCE STRING IS hello how are you do
DESTINATION STRINGS IS hello how are you do
-----------------------------------------------------------------------------------
char src[20];
char *dest; //runtime error
strcpy(dest,src);

char src[20],dest1[20];
char *dest;
dest=dest1; //it wont cause a runtime error now.
-----------------------------------------------------------------------------------
strcmp -- int strcmp (const char *str1, const char *str2)-returns int

str1<str2==> <0 //str1 is less than str2


str1>str2==> >0 //str1 is greater than str2
str1=str2==> =0 //str1 is equal to str2

#include<stdio.h>
#include<string.h>
int main()
{
char str1[20]="EMERTXE",str2[20]="EMERTXE";
int ret;
ret=strcmp(str1,str2);
if(ret < 0)
printf("str1 is less than str2\n");
else if(ret > 0)
printf("str1 is greater than str2\n");
else
printf("both the strings are equal\n");
return 0;
}
./a.out
both the strings are equal
-----------------------------------------------------------------------------------
with
char str1[20]="EMERTXE",str2[20]="EMERTX";

./a.out
str1 is greater than str2

-----------------------------------------------------------------------------------

char str1[20]="EMERTX",str2[20]="EMERTXE";
./a.out
str1 is less than str2

-----------------------------------------------------------------------------------
char str1[20]="EMERTXE",str2[20]="EMERTXe";
./a.out
str1 is less than str2 //ascii value of ’e’ is greater than ascii of ‘E’
-----------------------------------------------------------------------------------
• strcmp compares character by character using ASCII equivalent value.
85

• Once the character is mismatched, it will stop comparing.

• If any one of the string reached to null character stop comparing.


-----------------------------------------------------------------------------------
my_strcmp

#include<stdio.h>
int my_strcmp(char *str1, char *str2);
int main()
{
char str1[20]="EMERTXE",str2[20]="EMERTXe";
int ret;
ret=my_strcmp(str1,str2);
if(ret < 0)
printf("str1 is less than str2\n");
else if(ret > 0)
printf("str1 is greater than str2\n");
else
printf("both the strings are equal\n");
return 0;
}
int my_strcmp(char *str1, char *str2)
{
while(*str1 && *str2 && *str1==*str2)
{
str1++;
str2++;
}
if(*str1==*str2)
{
return 0;
}
else
{
return *str1-*str2;
}
}
./a.out
str1 is less than str2
-----------------------------------------------------------------------------------
86

JUNE 30
Strstr - search for the string
haystack
H I H O W A R E Y O U \0
0 1 2 3 4 5 6 7 8 9 10 11 12 13
needle
H O W \0

once there is a matching - in the haystack with the needle


it returns the characters from the matching .
Returning- HOW ARE YOU
returning the matching address of the haystack

H I H O W A R E Y O U \0
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<string.h>
int main()
{
char haystack[50]="HI HOW ARE YOU",needle[10]="HOW";
char *ret;
ret=strstr(haystack,needle); //returning address 1003
printf("RETURN: %s\n",ret);
return 0;
}
./a.out
RETURN: HOW ARE YOU
-----------------------------------------------------------------------------------
if there is no matching string it returns null

#include<stdio.h>
#include<string.h>
int main()
{
char haystack[50]="HI HOW ARE YOU",needle[10]="WHO";
char *ret;
ret=strstr(haystack,needle);
printf("RETURN: %s\n",ret);
return 0;
}
./a.out
RETURN: HOW ARE YOU
-----------------------------------------------------------------------------------
strchr - search for the character

#include<stdio.h>
#include<string.h>
int main()
{
char haystack[50]="HI HOW ARE YOU",needle[10]="WHO";
char *ret;
char ch='a';
ret=strchr(haystack,ch);
printf("RETURN: %s\n",ret);
return 0;
}
87

./a.out
RETURN: (null)

#include<stdio.h>
#include<string.h>
int main()
{
char haystack[50]="HI HOW ARE YOU",needle[10]="WHO";
char *ret;
char ch='A';
ret=strchr(haystack,ch);
printf("RETURN: %s\n",ret);
return 0;
}
./a.out
RETURN: ARE YOU
-----------------------------------------------------------------------------------
strcat:
concatination: merge the destination with source
#include<stdio.h>
#include<string.h>
int main()
{
char src[50]="hi how are you?",dest[50]="how you doing?";
strcat(dest,src); //stored in destination
printf("Concatination: %s\n",dest);
return 0;
}
./a.out
Concatination: how you doing?hi how are you? // simply append data
-----------------------------------------------------------------------------------
String token – strtok

-hi:’how are\you?.,./banglore

strtok will search for the token present in the string.


-once the token is found, replace that token with ‘\0’.

if token=’:’ ==> -hi\0


return the starting address of string from where it started searching
#include<stdio.h>
#include<stdio_ext.h>
#include<string.h>
int main()
{
char str[50],token[50];
char *ret;
printf("ENTER THE STRING\n");
scanf("%50[^\n]",str);
__fpurge(stdin);
printf("ENTER THE TOKEN\n");
scanf("%50[^\n]",token);
__fpurge(stdin);
ret=strtok(str,token);
printf("%s",ret);
return 0;
}
88

./a.out
ENTER THE STRING
hello ;;;;sdf;;;...
ENTER THE TOKEN
.
hello ;;;;sdf;;;
-----------------------------------------------------------------------------------
when ‘NULL’ is passed instead of string then strtok funtion will continue the task
from previously where it has stopped

when starting address and the return address are equal, it will continue the
operation

#include<stdio.h>
#include<stdio_ext.h>
#include<string.h>
int main()
{
char str[50],token[50];
char *ret;
printf("ENTER THE STRING\n");
scanf("%50[^\n]",str);
__fpurge(stdin);
printf("ENTER THE TOKEN\n");
scanf("%50[^\n]",token);
__fpurge(stdin);
ret=strtok(str,token);
printf("%s\n",ret);
ret=strtok(NULL,token);
printf("%s\n",ret);
return 0;
}
./a.out
ENTER THE STRING
hi:how areyou: jksjd
ENTER THE TOKEN
:;
hi
how areyou

./a.out
ENTER THE STRING
hi:how are oyou;sdf
ENTER THE TOKEN
89

;:
hi
how are oyou

./a.out
ENTER THE STRING
hi;:'hello:"?banglore=\
ENTER THE TOKEN
;:':?=\
hi
hello //the condition works for only two times
-----------------------------------------------------------------------------------

-->Takes a character from token and compares with each character form string,

--> if matching is found then that character will be replace with ‘\0’ and returns
the address from where it started seaching.

-->next time starts searching from ‘\0’ or previously where the funcion stopped.
strtok(NULL,token);
-->if string address and returned address is same after matching token, function
will continue the execution.

-->if no match found it will stop when string reach the null character.
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<stdio_ext.h>
#include<string.h>
int main()
{
char str[50],token[50];
char *ret;
printf("ENTER THE STRING\n");
scanf("%50[^\n]",str);
__fpurge(stdin);
90

printf("ENTER THE TOKEN\n");


scanf("%50[^\n]",token);
__fpurge(stdin);
ret=strtok(str,token);

while(ret != NULL) //NULL IS NOT A VALUE, IT IS A ADDRESS


{
printf("%s\n",ret);
ret=strtok(NULL,token);

}
return 0;
}
./a.out
ENTER THE STRING
hi;:'hello:"?banglore=\
ENTER THE TOKEN
;"':?\=
hi
hello
banglore //problem solved
-----------------------------------------------------------------------------------
ATOI – ASCII TO Integer

string-”123” convert to integer 123


-input as string %s
-output as integer - %d
1-ASCII return integer
2-ASCII return integer
3-ASCII return integer

input – 123abc ->123


input – abc123 -->0
input – -123 --> -123

#include<stdio.h>
#include<stdlib.h>
int main()
{
char str[10];int ret;
printf("enter the string\n");
scanf("%s",str);
ret=atoi(str);
printf("interger=%d",ret);
return 0;
}
./a.out
91

enter the string


sdf123
interger=0

./a.out
enter the string
13255ssdf
interger=13255
-----------------------------------------------------------------------------------
my_atoi() function
#include<stdio.h>
int my_atoi(char *str);
int main()
{
char str[20];
int ret;
printf("enter the string\n");
scanf("%s",str);
ret=my_atoi(str);
printf("interger=%d",ret);
return 0;
}
int my_atoi(char *str)
{
int temp=0,flag=0;
while(*str)
{
if(*str=='-')
flag=1;
else
temp=(temp*10) + (*str-48);
*str++;

}
if(flag==1)
return (temp * -1);
else
return temp;
}
/a.out
enter the string
-123
interger=-123
-----------------------------------------------------------------------------------
92

JULY 2
Storage classes
local/global
-->Stack
-->Heap
-->Code segment/text segment
-->Data segment

Static and global variables


--> memory allocated in data segment
1.BSS (Block Started by symbol), uninitialized (value will be 0)
2. unitialized

#include <stdio.h>
extern int num1; //can be initialised many times
extern int num1; //but same address will be pointed
-----------------------------------------------------------------------------------
#include<stdio.h>
int *foo()
{
int i=10;
return &i;
}
int main()
{
int *i;
i=foo();
printf("hi\n");
printf("*i=%d\n",*i);
return 0;
}
gcc demo.c
demo.c: In function ‘foo’:
93

demo.c:5:8: warning: function returns address of local variable [-Wreturn-local-


addr]
5 | return &i;
| ^~
segmentation fault
-----------------------------------------------------------------------------------
#include<stdio.h>
int *foo()
{
int i=10;
int *j=&i;
return j;
}
int main()
{
int i;
i=foo();
printf("hi\n");
printf("*i=%d\n",*i);
return 0;
}
./a.out
hi
*i=32766 //not correct answer
-----------------------------------------------------------------------------------

1. If you try to return the address of a local variable through pointer variable
then pointer returns the address and destroys the stack. If you try to access that
address by using %d,%f,%i...., it will result in segmentation fault/ garbage
value.

2. If you access the address by string format specifier ‘%s’ it will output as NULL
address or zero address.

REGISTER
-directly it will access from register
-register is closest memory to CPU

RESTRICTIONS:
It cannot be stored using address..

#include<stdio.h>
int main()
{
register int i=10;
i=90;
printf("i=%d\n",&i); //error
return 0;
}
94

JULY 3
#include<stdio.h>
int *foo() //returning address
{
static int i=10; //stored in data segment, destroyed at the end of
int *j=&i; //program.
return j;
}
int main()
{
int *i;
i=foo();
printf("i=%d\n",*i);
return 0;
}
./a.out
i=10

if given [ int foo() ] --> warning with segmentation fault.


-----------------------------------------------------------------------------------
#include<stdio.h>
char *foo()
{
static char ca[12]="Hello World";
return ca;
}
int main()
{
char *ca;
ca=foo();
printf("ca=%c\n",*ca);
return 0;
}
./a.out
ca=H
-----------------------------------------------------------------------------------

#include<stdio.h>
char *foo()
{
static char ca[12]="Hello World";
return ca;
}
int main()
{
char *ca;
ca=foo();
printf("ca=%s\n",ca);
return 0;
}
./a.out
ca=Hello World
-----------------------------------------------------------------------------------
95

#include<stdio.h>
int main()
{
static int i=5; //stored and made changes in data segment
if(--i)
{
main();
}
printf("i=%d\n",i);
return 0;
}
./a.out
i=0 //static once changed , remains the same
i=0
i=0
i=0
i=0
-----------------------------------------------------------------------------------

#include<stdio.h>
int main()
{
static int i=5;
if(--i)
{
return main();
}
printf("i=%d\n",i);
return 0;
}
./a.out
i=0
//found return at the destruction of last stack frame. The stack is deleted from
last to first, even so static value remains the last changed value
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
static int i=5;
if(--i)
{
printf("i=%d\n",i);
return main();
}
return 0;
}
./a.out
i=4
i=3
i=2
i=1
96

-----------------------------------------------------------------------------------

#include<stdio.h>
int foo()
{
static int i;
return i;
}
int main()
{
static int x=foo();
printf("x=%d\n",x);
return 0;
}
compile time error:
error: initializer element is not constant
-----------------------------------------------------------------------------------
int y=10;
static int x=y; //also error
-----------------------------------------------------------------------------------
int i=10;
static int *j=&i; //also error
-----------------------------------------------------------------------------------
#include<stdio.h>
int *foo()
{
int i=10;
static int *j;
j=&i;
return j;
}
int main()
{
int *i;
i=foo();
printf("*i=%d\n",*i);
return 0;
}
./a.out
*i=10 //static pointer
-----------------------------------------------------------------------------------
#include<stdio.h>
int x; //data will be stored and modified in BSS not
DS
int foo()
{
printf("x=%d\n",x);
x++;
}
int main()
{
foo();
97

printf("x=%d\n",x);
return 0;
}
./a.out
x=0
x=1

-----------------------------------------------------------------------------------

cant use auto as global //error


cant use register as global either //error

-----------------------------------------------------------------------------------
#include<stdio.h>
int x=10;
int x; //ignored
int foo()
{
printf("x=%d\n",x);
x++;
}
int main()
{
foo();
return 0;
}
./a.out
x=10
-----------------------------------------------------------------------------------
#include<stdio.h>
int x=10;
int x=20; //error: redefinition of global varible
int foo()
{
printf("x=%d\n",x);
x++;
}
int main()
{
foo();
return 0;
}
-----------------------------------------------------------------------------------
int x=20;
int x;

./a.out
x=20
-----------------------------------------------------------------------------------
98

JULY 5
Storage Classes – Global

• Translation unit – A source file + header file(s) forms a translation unit


• Compiler translates source code file written in ‘C’ language to machine
language
• A program is constituted by the set of translation units and libraries
• An identifier may be declared in a scope but used in different scopes (within
a translation unit or in other translation units or libraries)
• Linkage – An identifier declared in different scopes or in the same scope
more than once can be made to refer to the same object or function by a
process called linkage
• There are three type of linkages – internal, external and none

External linkage:
• A global variable declared without storage class has “external linkage”.

Internal linkage:
• A global variable declared with static storage class has “Internal” linkage.

None linkage:
• Local variables have “none” linkage.

It looks for previous visible declarations

Extern file1.c file2.c --> ./a.out


-----------------------------------------------------------------------------------
#include<stdio.h>
int num=10;
int main()
{
int num=90; //ignores and go for global
{
extern int num;
printf("%d\n",num);
}
printf("%d\n",num);
}

./a.out
10
90
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int num=90;
{
extern int num; //compile time error , no global variable
printf("%d\n",num);
}
printf("%d\n",num);
}
-----------------------------------------------------------------------------------
#include<stdio.h>
int num=10;
int main()
99

{
int num=90;
{
int num=20;
printf("%d\n",num);
}
printf("%d\n",num);
}
./a.out
20 //priority is given to local than global variable
90
-----------------------------------------------------------------------------------
priority is given to global variable than extern

extern- refer ppt-441


100

JULY 6
Demo.c
#include<stdio.h>
int func_1();
int num;
int main()
{
while(1)
{
num++;
func_1();
sleep(1);
}
}
demo1.c
#include<stdio.h>
static int num;
extern int num;
int func_1()
{
printf("num is %d from file2\n",num);
return 0;
}
./a.out
num is 0 from file2
num is 0 from file2
num is 0 from file2
num is 0 from file2
num is 0 from file2
^C

#include<stdio.h>
extern int num;
static int num; //error static follows the non-static declaration
int func_1()
{
printf("num is %d from file2\n",num);
return 0;
}
-----------------------------------------------------------------------------------
demo.c

#include<stdio.h>
int func_1();
int num;
int main()
{
while(1)
{
num++;
func_1();
sleep(1);
}
}

demo1.c
#include<stdio.h>
101

extern int num;


int func_1()
{
printf("num is %d from file2\n",num);
return 0;
}

./a.out
num is 1 from file2
num is 2 from file2
num is 3 from file2
num is 4 from file2
num is 5 from file2
num is 6 from file2
num is 7 from file2
^C
-----------------------------------------------------------------------------------
extern int num;
extern char num; //conflicting types, error
-----------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
int x;
{
int x = 10;
{
extern int x;
printf("x %d\n", x);
}
printf("x %d\n", x);
}
printf("x %d\n", x);
return 0;
}
int x = 20;
./a.out
x 20
x 10
x 0 //garbage
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
extern char x;
printf("x=%c\n",x);
return 0;
}
int x=0x31; //conflicting type error

different data type of extern cannot be initialised in same program


-----------------------------------------------------------------------------------
102

#include <stdio.h>
int main()
{
int x;
{
int x = 10;
{
extern int x = 20; //error , block initialisation is not allowed
printf(“x %d\n”, x);
}
printf(“x %d\n”, x);
}
printf(“x %d\n”, x);
}
return 0;
int x;
-----------------------------------------------------------------------------------

#include<stdio.h>
int main()
{
int x;
extern int x; //error extern should be separated form local
printf("x=%c\n",x);
return 0;
}
int x;
-----------------------------------------------------------------------------------
demo.c
#include<stdio.h>
#include<unistd.h>
int func();
int num;
int main()
{
while(1)
{
num++;
func();
sleep(.2);
}
return 0;
}
demo1.c
#include<stdio.h>
extern char num;
int func()
{
printf("num is %d from file 2\n",num);
return 0;
}

//prints from 0 to 127 then -128 to -1 and then repeats.


103

//in short the character range is printed endlessly


-----------------------------------------------------------------------------------

demo.c
#include<stdio.h>
#include<unistd.h>
int func();
int num;
int main()
{
while(1)
{
num++;
func();
sleep(.2);
}
return 0;
}
demo1.c
#include<stdio.h>
extern int num;
static int func() //static restricts the function scope to within {
//file, cannot call from external file.
printf("num is %d from file 2\n",num);
return 0;
}
//error
-----------------------------------------------------------------------------------
extern int num;
static int num; //compiler error, linkage disagreement

int num; //if linkage is there,works as extern, or else global


static int num; //anyway error due different classes

static int num;


int num; //linkage disagreement, as no explixit extern
-----------------------------------------------------------------------------------
{
extern int num; //for local extern, static not work
} //error
( in global )
static int num=10; //redeclaration error
-----------------------------------------------------------------------------------
points to remember:
Auto
• Can’t be used with global variable
• local variable will always dominate the global
• memory is allocated in stack
• default value is garbage

Register
• If you are accessing the value repeatedly, make the variable as register.
• Waiting is not recommended, emergency
104

• limited register in the CPU, if register memory is available then it will


allocate else memory will be in main memory(stack).
• &address – cannot use address of register variable
• register can be of pointers and can store local variable address

Static -> local/global


• BSS/data segment (initialised block)
• lifetime will be till u complete the program execution
• in the definition the value should be constant
▪ static int num=y; //error
• function parameters cannot be static
▪ void foo(static int num) //error
▪ because memory is allocated only once, value doesn’t change for each
stack, retains the same
• Global static variable or function will have internal linkage, scope will be
within the file.
• Static address can be passed
Global
• can do extern
• extern always search for previous visible declaration
• While we extern the variable between file(program) then data type can be
changed, but it is now allowed if linkage is within the file.

int num=10;
extern char num; //error, different data type

• If extern is block scope{}, then linkage will be global without any storage
class.(int num or global int num)
Same with static is an error.
-----------------------------------------------------------------------------------
105

JULY 7
Rule 1 – Pointer is an integer
• Address stored in pointer is always an integer (decimal,octal, hexa...)

Rule 2 - Referencing and De-referencing


• &-refer to address
• * -defer to value stored in address

Rule 3 - Pointing means Containing


• Pointer variable holds the address

Rule 4 - Pointer type


• To decide how many bytes to be fetched at deferencing

Rule 5 – Pointer Arithmetic


“value(p+i)=value(p)+ i*sizeof(*p)”
-----------------------------------------------------------------------------------
Rule 6 - Pointing to nothing

int *ptr, in this the ptr points to

1.valid address
-->used by user space- garbage value
2.Invalid address
-->kernel space-not allowed to used by normal user
-->another process points the same address
-->segmentation fault

pointing to NULL address


int *ptr=NULL

NULL is a macro, which says it will point to (void*)0

-->treat the address 0 as a void pointer

0--> is always dedicated in kernel space which will tell the OS that the process
which is using 0 is not important.

Dereferencing of NULL is not possible, also gives error, but atleast error from
known cause
int *num;
num=NULL;

int *num=NULL;

you must use type casting(type) to dereference


-----------------------------------------------------------------------------------
Most of the compiler
-->pointer arithmetic and dereferencing is not possible for NULL
-->type casting to perform above operation

GCC
-->pointer arithmetic
-->sizeof(ptr)-->return 1 //for NULL

-----------------------------------------------------------------------------------
#include<stdio.h>
106

int main()
{
void *ptr;
printf("%zu\n",sizeof(void)); //void size is 1
}
./a.out
1

-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
//int *ptr=NULL;
void *ptr;
printf("%zu\n",sizeof(void));
printf("%zu\n",sizeof(void*)); //system dependent
}
./a.out
1
8
-----------------------------------------------------------------------------------

refer ppt 270


107

JULY 8
NULL pointer is logically understood as pointing to nothing.

You must use “type” casting to deference

gcc allows pointer arithmetc, because gcc treats sizeof(void) as1

void is only possible with pointer


-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
char ch='A';
void *vptr=&ch; //pointer arithmetic is possible but not deferencing
printf("%c\n",*vptr);
}
//error: invalid use of void expression
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
char ch='A';
void *vptr=&ch;
printf("%c\n",*(char*)vptr);
}
./a.out
A

*vptr==> no data type so error will occur

to fetch the value typecaste or convert void pointer


*(char *)vptr ==> char *vptr
-----------------------------------------------------------------------------------
scanf(“%c”,(char *)vptr) ==> storing value in address no * required
==>i.e no required for *(char *)vptr

#include<stdio.h>
void swap( void *, void *, int);
int main()
{
int num1, num2;
printf("enter num1 and num2 :");
scanf("%d %d",&num1,&num2);
printf("BEFORE SWAPPING\nnum1 :%d num2: %d",num1,num2);
swap(&num1, &num2, sizeof(num1));
printf("\nAFTER SWAPPING\nnum1 :%d num2: %d",num1,num2);
return 0;
}
void swap(void *ptr1, void *ptr2, int size )
{
char temp;
int i;
for(i=0;i<size;i++)
108

{
temp = *(char *)ptr1; //swap byte by byte for size times
*(char *)ptr1 = *(char *)ptr2;
*(char *)ptr2 = temp;
ptr1++;
ptr2++;
}
}

/a.out
enter num1 and num2 :2
5
BEFORE SWAPPING
num1 :2 num2: 5
AFTER SWAPPING
num1 :5 num2: 2
-----------------------------------------------------------------------------------

Static memory – allocated at compile time

Dynamic memory- allocated at run time

Static Dynamic

• Compile time • Run time



• Constant , cannot extend, cannot • Whenever u want u can shrink,
shrink, extend, delete the memory.
• cannot delete.

int main() • --> allowed for dynamic


{
int num=10;
scanf, printf;
//delete num- not allowed
//increase the memory is not
allowed
}
• -->Stack segment, data segment, • -->heap segment
code segment

• Address is fixe • Because we use pointer, we change


the address stored inside the
pointer

• Named memory allocation • Unnamed


109

• Managed by compiler • By user

calloc, realloc, malloc, free --> stdlib.h


110

JULY 10
DYNAMIC MEMORY ALLOCATION-->(Heap memory)

void *malloc(size_t size) --->size_t==>32 bit – unsigned int


==>64 bit – unsigned long int
if successfully allocated the memory it returns the pointer of the allocated
memory, else returns NULL.

Int *ptr;
ptr=malloc(6); //malloc always returns the void pointer
//but type casting is done implicitly to integer in this
case.
Or ptr= (int*)malloc(6); //explicit type casting

syntax:
malloc(size_t size);

1.allocates number of bytes from heap segment

2. If the memory is allocates successfully then it returns the base


address/starting address to the pointer.

3. malloc returns the void pointer, if stored pointer is of different types


compiler will do the typecasting implicitly.

4. Upon unsuccessfull allocation , it will return NULL .


-----------------------------------------------------------------------------------
----------------
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char *ptr;
ptr=malloc(5);
strcpy(ptr,"KARTHIKEYAN"); //illegal access, but no error
//may cause segmentation fault
puts(ptr);
return 0;

}
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char *ptr;
//ptr=malloc(5); commented
strcpy(ptr,"KARTHIKEYAN"); //segmentation fault, as it maybe
//used somewhere else
puts(ptr);
return 0;

to avoid that confusion


111

char *ptr=NULL; //to know the cause of fault

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char *ptr;
ptr=malloc(5000000000000);
if(ptr==NULL)
printf("MEMORY IS NOT ALLOCATED");
else
{
strcpy(ptr,"KARTH");
puts(ptr);
}
return 0;

}
./a.out
MEMORY IS NOT ALLOCATED
-----------------------------------------------------------------------------------
ptr= malloc(5*sizeof(int)); //legal

void *calloc(size_t nmemb, size_t size);

it allocates memory by block of bytes

calloc(5,1); //allocates 5 blocks of one byte

calloc(5,2); //allocates 5 blocks of two bytes (10bytes)

-->accessing is not done in block wise, only allocation is done block wise.

Malloc Calloc
1. it takes one argument size 1. 2 arguments, number of element and
size of each elements

2. by default garbage value 2. by default each memory block will be


initialised with zero

3. time complexity is less because of no 3. because it initialise each byte with


initialization zero it takes more time than malloc

4. used in basic allocation, structure, 4. preferred for array-


linked list --> initialise to zero

-----------------------------------------------------------------------------------
void free (void *ptr);
112

1. frees the allocated memory, which must have been returned by a previous call to
malloc(), calloc() or realloc()

2. Freeing an already freed block or any other block would lead to undefined
behaviour

3.Freeing NULL pointer has no effect.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char *ptr;
ptr=malloc(50);
strcpy(ptr,"KARTH");
puts(ptr);
free(ptr);
strcpy(ptr,"pavi");
puts(ptr);
return 0;

}
./a.out
KARTH
pavi
-----------------------------------------------------------------------------------
free (ptr); //pointer will called as dangling pointer
ptr=NULL; //as the pointer is not freed from memory pointing
//coding practice to avoid undefined behaviour

void *realloc( void *ptr, size_t size);

changes the size of the already allocated memory by malloc or calloc

return the pointer of the allocated memory on success, else returns NULL.

When you shrink from 4 bytes to 3 bytes, data in the deleted byte is lost.

If the memory is not free for extending ,the realloc will search for new location
of continuous data and copy the old contents, and return the base address.

If fails, it returns the NULL address

always use new pointer for extending --> because maybe data will be lost
-----------------------------------------------------------------------------------

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
113

char str[50];
printf("enter the string: ");
scanf("%[^\n]",str);
char *ptr;
ptr=strdup(str);
puts(str);
}
./a.out
enter the string: hai heos
hai heos
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void *my_strdup(char *str);
int main()
{
char str[50];
printf("enter the string: ");
scanf("%[^\n]",str);
char *ptr;
ptr=my_strdup(str);
puts(str);
}
void *my_strdup(char *str)
{
return str;
}
./a.out
enter the string: hello how are you doing
hello how are you doing
-----------------------------------------------------------------------------------
114

JULY 13 Const
int const i;
const int i=10 ;

//read-only, non-modifiable
-----------------------------------------------------------------------------------
1. int *num=NULL;
1000
num

*num=10; //segmentationNULL
fault, can’t assign value to a null pointer

2. int a=10;
int const *num=&a;
printf(“%d”,*num);

./a.out
10
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int a=10;
int const *num=&a;
printf("%d\n",*num);
*num=20; error: assignment of read-only location ‘*num’
return 0;
}
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int a=10;
int const *num=&a;
printf("%d\n",*num);
a=20; //allowed because a is modifiable through a and not
//*num
printf("%d\n",*num);
return 0;
}
./a.out
10
20
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int a=10,b=20;
int const *num=&a;
printf("%d\n",*num);
num=&b; //possible, only the value of variable is cannot be
//modified through *num
printf("%d\n",*num);
return 0;
}
./a.out
10
115

20
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int a=10;
int * const num=&a; //here the pointer variable is constant
printf("%d\n",*num);
int b=20;
num=&b; //error, pointer value cannot be modified for
//int* const
printf("%d\n",*num);
return 0;
}

but a=20 is possible


-----------------------------------------------------------------------------------

int const *num=&a; Int* const num=&a;


const int *num=&a; ==>num is constant
num=&b; //error
==> *num=10; //error *num=20; //valid
num=&b; //valid a=20; //valid
a=10; //valid b=20; //valid

int const * const num =&a;


==> both address and value are read only

num=&c; //error
*num=90; //error
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int num=20;
const int *ptr=&num;
printf("%d\n",*ptr);
*ptr++;
printf("%d\n",*ptr);
return 0;
}
./a.out
20
394519584 //garbage, pointer address can be modified in this

in this
(*ptr)++; //error: changing value through variable
-----------------------------------------------------------------------------------
116

#include<stdio.h>
int main()
{
const int num=20;
int *ptr=&num; //warning because ptr is not const but works fine
printf("%d\n",*ptr);
*ptr=30;
printf("%d\n",*ptr);
return 0;
}
./a.out
20
30
-----------------------------------------------------------------------------------
int const *num =NULL; -->The location, its pointing to is constant
int *const num=NULL; -->The pointer is constant
Const int *const num=NULL; --> both are constants

DO’s AND DONT’s

1. pointer arithmetic

int *ptr=&num;
ptr=ptr+1; //garbage

ptr=ptr-1; //garbage

ptr=ptr*1; //error
ptr=ptr/1; //error

multiplication and division on the pointers with a constant is not allowed


-----------------------------------------------------------------------------------
2. ADDING 2 POINTERS

int *ptr1=&num1;
int *ptr2=&num2;
int *ptr;

ptr=ptr1+ptr2; //compilation error


ptr=ptr1*ptr2; //error
ptr=ptr1/ptr2; //error
117

ptr=ptr1-ptr2; //possible, when both are same type


-----------------------------------------------------------------------------------
int num=0;

scanf(“%d”,num); //as & is not given, pointing TO NULL leads to


//segmentation fault
-----------------------------------------------------------------------------------
int *num=0; //0 acts as NULL
printf(“%d”,*num); //segmentation fault, at run time

-----------------------------------------------------------------------------------

int *num; //wid pointer, initialised to nothing

static int *num; //not a wild pointer, as initialised to 0 implicitly

-----------------------------------------------------------------------------------
The bus error is a fault, due to pointers sharing the same address.

-----------------------------------------------------------------------------------
118

JULY 14 MULTILEVEL POINTER

A pointer pointing to another pointer.

/home/karthi/c class/c class 7.14/1.c


#include<stdio.h>
int main()
{
int num = 10;
int *ptr1 = &num;
int **ptr2 = &ptr1;
int ***ptr3 = &ptr2;

printf("%d\n", ptr3);
printf("%d\n", *ptr3);
printf("%d\n", **ptr3);
printf("%d\n", ***ptr3);
}

/*
./a.out
-516338712
-516338720
-516338724
10
*/
-----------------------------------------------------------------------------------
/home/karthi/c class/c class 7.14/2.c
#include<stdio.h>
void foo(int *num)
{
num=num+5; //hasnt done anything to the value of the variable
}
int main()
{
int x=10;
printf("before: x=%d\n", x);
foo(&x);
printf("after:x=%d\n ",x);
return 0;

/*
before: x=10
after:x=10
*/
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int a[3]={1,2,3};
printf("%lu\n",a+1);
printf("%lu\n",&a[0]+1);
printf("%lu\n", &a+1); //represents whole array( multiplied with size of
//whole array)
}
119

./a.out
140734154636336
140734154636336
140734154636344 //base address + 12
-----------------------------------------------------------------------------------
2D array:

data_type arr[ROWS][COLS];

no. of elements =ROWS * COLS;


total memory allocated = rows * cols *sizeof(array_data_type)

Printing 2D arrays:
#include<stdio.h>
int main()
{
int a[2][3]={1,2,3,4,5,6};
int i, j;
for(i=0; i<2; i++,printf("\n"))
{
for(j=0; j<3; j++)
{
printf("%d ",a[i][j]);
}
}
}

./a.out
1 2 3
4 5 6
-----------------------------------------------------------------------------------
Different ways of interpreting the 2D array

1. arr[i][j]

2. arr[i] ==> x
arr[i][j] ==> x[j]
==>*(x+j) ==> *(x+j *(sizeof(datatype of array))

*(arr[i]+j)

3. *(*(arr+i)+j))

4. (*(arr+i))[j]
120

JULY 15
Deferencing 2D array will give 1D array.
Deferencing that 1D array will give the elements.

Array of pointers - internally 2D array


--> collection of pointers

#include<stdio.h>
int main()
{
int a=10, b=20, c=30;
int *ptr[3];
ptr[0] = &a;
ptr[1] = &b;
ptr[2] = &c;
for(int i=0;i<3;i++)
printf("ptr[%d]=%d\n",i,*ptr[i]);
return 0;
}
/a.out
ptr[0]=10
ptr[1]=20
ptr[2]=30
-----------------------------------------------------------------------------------
#include<stdio.h>
void print_array(int p[]) //**ptr == *ptr[]
{
int i;
for(i=0; i<3;i++)
{
printf("%d ",*p[i]);
printf("at %p\n",p[i]);
}
}
int main()
{
int a=10, b=20, c=30;
int *ptr[3]={&a, &b ,&c};
print_array(ptr);
return 0;
}
./a.out
10 at 0x7ffcefb31034
20 at 0x7ffcefb31038
30 at 0x7ffcefb3103c
-----------------------------------------------------------------------------------

ARRAY OF STRINGS:

char str[3][8] = {“Array” ,“of”, “strings”}; //in code segment


//cant be modified

if base address of “Array” is 100


==> str[0] ==> *(str+0)
==> ((100 + 0* sizeof(1d array))
==> *(100)
==> 100 //because it is a 2D array
121

-----------------------------------------------------------------------------------

#include<stdio.h>
int main()
{
char s[3][8] = {"Array","of","strings"};
printf("%s %s %s\n",s[0],s[1],s[2]);
return 0;
}
./a.out
Array of strings
-----------------------------------------------------------------------------------
122

JULY 16
Pointer to an array ==> explicitly used for 2D array

datatype(* ptr_name)[SIZE];

int (*ptr) [3]; //ptr is a pointer to an araay of 3 integer elements

#include<stdio.h>
int main()
{
int array[3]= {1,2,3};
int *p1;
int (*p2)[3];
p1 = array;
p2 = &array;
printf("%lu %lu \n",p1+0, p2+0);
printf("%lu %lu \n",p1+1, p2+1);
printf("%lu %lu \n",p1+2, p2+2);
}

./a.out
140726800885084 140726800885084
140726800885088 140726800885096 //a leap of sizeof(array)(12) address
140726800885092 140726800885108
-----------------------------------------------------------------------------------
Creation of 2D array dynamically
-->2D array is created by using dynamic memory allocation -malloc, calloc

** ==> multilevel pointer


[][] ==> 2d array
*[] ==> array of pointers
(*)[] ==> pointer to an array

int (*p)[3] ==> sizeof(*p) ==> sizeof(data_type of *p) * number of elements


==> 4*3 =12bytes

POINTER TO AN 2D ARRAY:

int (*p)[3];
int a[2][3]={1,2,3,4,5,6};
p=a;

CREATION OF 2D ARRAY:
1. Both Static --> Both rows and columns are fixed

int arr[2][3];

2. first static , 2nd dynamic


--> rows are fixed , columns are variable
--> columns are allocated by using dynamic memory allocation
--> columns are address --> array of pointers
123

reading columns from user


3
for(int i=0;i<2;i++)
{
ptr[i] = malloc(3 *sizeof(int));
}

how much memory needed,


for 32 bit
ptr 8
heap 24
-----
32 byte
-----

for 64 bit
ptr 16
heap 24
-----
40 bytes
3. First dynamic, second static

==> rows are variable, cols are fixed

==> pointer to an array concept

int (*ptr)[3]
rows = read value frokm user
=2
ptr = malloc (sizeof(*ptr) *rows)
= 24 bytes

4. BOTH ARE DYNAMIC

if row=2, col=2;
int *arr;

1. create rows
arr = malloc(rows * sizeof(int *));

2. Create columns
for( int i=0; i<row; i++)
arr[i] = malloc(col * sizeof(int));
124

JULY 19 ADVANCED FUNCTIONS

Command Line Arguments


--> gcc, ls, vi, mkdir, cd, ./a.out etc.,

int main (int argc, char *argv[], char *envp[] )


{

1. argc ==> argument count, no. Of arguments in command line.

: gcc filename.c ==>here ‘space’ acts as delimiter. Here, argc=2

2. char *argv[] ==> argument vector --> array of pointer


==> base address of command line arguments

char **argv -- same

3. char *envp[] --> environmental variables

char **envp -- same

--> with respect to system


--> system information

-----------------------------------------------------------------------------------
Consider : ./a.out 10 20 30 hi

argc = 5

char *argv[] --> address of strings --> command line values

#include<stdio.h>
int main(int argc, char **argv)
{
int i;
printf("NO OF ARGUMENT(s) : %d\n", argc);
printf("List of Arguments(s)\n");
for(i=0; i<argc; i++)
printf("\t%d - %s\n",i+1,argv[i]);
return 0;
}

./a.out 10 20 30 40 hi
NO OF ARGUMENT(s) : 6
List of Arguments(s)
1 - ./a.out
2 - 10
3 - 20
4 - 30
5 - 40
6 – hi
-----------------------------------------------------------------------------------
125

#include<stdio.h>
int main(int argc, char **argv, char **envp)
{
int i;
printf("NO OF ARGUMENT(s) : %d\n", argc);
printf("List of Arguments(s)\n");
for(i=0; envp[i]; i++)
printf("\t%d - %s\n",i+1,argv[i]);
return 0;
}

//prints the environmental varibles

#include<stdio.h>
int main(int argc, char **argv, char **envp)
{
int i;
printf("NO OF ARGUMENT(s) : %d\n", argc);
printf("List of Arguments(s)\n");
for(i=0; envp[i]; i++);
printf("count=%d",i);
return 0;
}
prints the count of environmental variables
./a.out
NO OF ARGUMENT(s) : 1
List of Arguments(s)
count=61
-----------------------------------------------------------------------------------
to add variabes and value to the environmental

export arr=[10,20,30];
echo &arr
[10,20,30]

#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv, char **envp)
{
char *ptr;
ptr = getenv("NUM");
puts(ptr);
}
./a.out
10
-----------------------------------------------------------------------------------
To create environmental variables

setenv(“nameofvar”, “value of var”, status)

status=0 --> it will create environmental variable with name


126

if the variable already exist in the system it will nor assign the new
value

status =1 --> if the variable already exist in the system it will replace the old
value to assign the new value

#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv, char **envp)
{
char *ptr;
ptr = getenv("NUM");
puts(ptr);
setenv("NUM","20",0);
ptr = getenv("NUM");
puts(ptr);
return 0;
}
./a.out
10
10
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv, char **envp)
{
char *ptr;
ptr = getenv("NUM");
puts(ptr);
setenv("NUM","20",0);
ptr = getenv("NUM");
puts(ptr);
return 0;
}
10
20 //but the change is not permanent, but within the lifetime
//of the program
-----------------------------------------------------------------------------------

FUNCTION POINTER

--> Pointer that will store the address of the function/ points to the function.
--> execute function independently

return_type (*fptr) (list of arguments(s) data type); //prototype

eg.
int (*foo)(int.int) ==> pointer to a function that has return type
of int and two arguments of type int.

*foo – function pointer


-Store function address

int *fptr (int, int) ==> function prototype which returns the address
int ( *fptr) (int,int) ==> function prototype
127

Function code would be stored in the text segment with an address associated with
it.
-----------------------------------------------------------------------------------
#include<stdio.h>
int add(int, int);
int add(int a, int b)
{
}
int main()
{
printf("%p\n",add);
printf("%p\n",&add);
}
./a.out
0x55f5872c7149
0x55f5872c7149

-----------------------------------------------------------------------------------
128

JULY 20
#include<stdio.h>
int add(int, int);
int add(int a, int b)
{
}
int main()
{
int (*fptr)(int,int);
fptr= add; //or &add
printf("%p\n",add);
printf("%p\n",fptr);
printf("%p\n",&fptr);
return 0;
}
./a.out
0x5601982ba169
0x5601982ba169 //address of the function
0x7ffe1ab832a0 //address of fptr
-----------------------------------------------------------------------------------
fptr= add //acts same as using add anywhere

*fptr = *add ===> value stored in address, in this case a function , so it


will throw a warning

Calling a function through pointer

(*fptr)(10,20);
fptr(10,20);
add(10,20);
-----------------------------------------------------------------------------------

#include<stdio.h>
int add(int, int);
void foo(int (*)(int, int));
int add(int a, int b)
{
return a+b;
}
int main()
{
foo(add); //would pass the address of the function
return 0; //so to receive we should use pointer
}
void foo(int (*ptr)(int, int))
{
printf("%d\n",ptr(10,20));
}
./a.out
30
-----------------------------------------------------------------------------------
129

#include<stdio.h>
int add(int, int);
int sub(int a, int b);
int foo(int (*ptr)(int, int), int a, int b);
int main()
{
int (*fptr)(int , int);
fptr=add;
printf("1.=%d\n",foo(fptr, 10,20)); //foo --> add --> foo -->main

fptr=sub;
printf("2.=%d\n",foo(fptr,10,20)); //foo --> sub --> foo -->main

return 0;
}
int add(int a, int b)
{
return a+b;
}
int sub(int a, int b)
{
return a-b;
}
int foo(int (*ptr)(int, int), int a, int b)
{
return ptr(a,b);
}
/a.out
1.=30
2.=-10
-----------------------------------------------------------------------------------
ARRAY OF FUNCTION POINTERS:

#include<stdio.h>
int add(int, int);
int sub(int a, int b);

int main()
{
int (*fptr[])(int , int)={add, sub};
printf("1.=%d\n",fptr[0]( 10,20));

printf("2.=%d\n",fptr[1](10,20));

return 0;
}
int add(int a, int b)
{
return a+b;
}
int sub(int a, int b)
{
return a-b;
}
./a.out
130

1.=30
2.=-10
-----------------------------------------------------------------------------------

atexit()

-->inbuilt function
--> while exiting from (function/ process) atexit() will execute the function
registered by the user.

--> at exit(0), or return 0

#include<stdio.h>
#include<stdlib.h>
void my_exit(void);
void test(void);
static int *ptr;

int main()
{
atexit(my_exit); //registering a function for atexit
ptr=malloc(10);
test();
printf("hello\n"); //as program exited , this never executed
return 0;
}
void my_exit(void)
{
printf("exiting program\n");
if(ptr)
{
free(ptr);
printf("ptr had memory allocated, so i freed, do you feel thats wrong?\
nAnd cant prceed from here on\n");
}
}
void test(void)
{
puts("in test");
exit(0);
}

./a.out
in test
exiting program
ptr had memory allocated, so i freed, do you feel thats wrong?
And cant prceed from here on
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
void foo(void)
{
printf("in foo\n");
}
void foo1(void)
{
131

printf("in foo1\n");
}
void foo2(void)
{
printf("in foo2\n");
}
void foo3(void)
{
printf("in foo3\n");
}

int main()
{
atexit(foo);
atexit(foo1);
atexit(foo2);
atexit(foo3); //executes in reverse order
return 0;
}
./a.out
in foo3
in foo2
in foo1
in foo
-----------------------------------------------------------------------------------
132

JULY 21

qsort()

--> arrange the value in descending/ascending order

--> generic function – it will work for any type of data

--> qsort is a generic function which is used to sort array of any type int, float,
double, strings, character.

--> function pointer can be used to write generic function

--> user has to write compare function depending on whether ascendin/descending


order.

Prototype:
void qsort (void base, size_t nmemb, size_t size, int(compar)(const void *, const
void *));

void *base --> can store any type of address

size_t nmemb --> number of elements

size_t size --> size of array

int(*compar)(const void*, const void *) --> function pointer

--> function which returns integer and takes 2 address of any type and constant

--compare function will do the comparison b/w value present at 2 address, and
returns

0 ==> if both the values are equal


-1 ==> if first value is less than second
1 ==> if first one is greater than second
-----------------------------------------------------------------------------------

#include<stdio.h>
#include<stdlib.h>
int sa(const void *a, const void *b)
{
return *(int *)a > *(int *)b;
}
int sd(const void *a, const void *b)
{
return *(int *)a < *(int *)b;
}

void print(int *a, unsigned int size)


{
int i = 0;

for(i; i < size; i++)


printf("%d", a[i]);
133

printf("\n");
}

int main()
{
int a[5] = {9, 2, 6, 1, 7};
qsort(a, 5, sizeof(int), sa);
printf("Ascending order of array: ");
print(a,5);

qsort(a, 5, sizeof(int), sd);


printf("Descending order of array :");
print(a,5);

return 0;
}
./a.out
Ascending order of array: 12679
Descending order of array :97621
-----------------------------------------------------------------------------------

VARIADIC FUNCTIONS( VARIABLE NUMBER OF ARGUMENTS)

syntax:
return data_type function_name(parameter list, ...)

Whenever writing a variadic fucntion there has to end point(mostly’\0’)

The macors are defined in header file stdarg.h

va_list --> type va_list is used for argument pointer variables

va_start --> used to point to first optional argument

va_arg --> the next successive arguments are fetched through this

va_end --> to clear the pointer

#include<stdio.h>
#include<stdarg.h>
int add(int count, ...)
{

va_list ap;
int iter, sum;

/*Initialise the arg list*/


va_start(ap, count);

sum=0;
for(iter=0; iter<count; iter++) //illegal access leads to garbage
val
{
//Extract args
sum += va_arg(ap, int);
134

//cleanup
va_end(ap);

return sum;
}
int main()
{
int ret;
ret = add(3, 2, 4, 4);
printf("SUM IS %d\n", ret);

ret= add(5, 3, 5, 8, 9, 2); //here [0]--> is the count of variables


printf("SUM IS %d\n",ret); //the user passed, not implicit

return 0;
}

./a.out
SUM IS 10
SUM IS 27

1. ap --> pointer to first argument

2. va_start will make ap to point count

3. sum = sum+va_arg(ap, int); //va_arg automatically access the next arg

-----------------------------------------------------------------------------------

#include<stdio.h>
#include<stdarg.h>

void my_printf(const char *, ...);


int main()
{
my_printf("%s %d %f %c\n","Hello World ", 100, 10.2,'c');
return 0;
}

void my_printf(const char *format, ...)


{
va_list ap;
int x;
float f;
char c;
char *s;

va_start(ap, format);
while(*format)
{
if(*format == '%' )
{
format++;
switch(*format)
135

{
case 'd':
x = va_arg(ap, int);
fprintf(stdout, "%d", x);
format++;
break;
case 'f':
f = va_arg(ap, double); //float is promoted to double
in ...
fprintf(stdout, "%f", f);
format++;
break;
case 'c':
c = va_arg(ap, int );
fprintf(stdout, "%c", c);
format++;
break;
case 's':
s = va_arg(ap, char*);
fprintf(stdout, "%s", s);
format++;
break;

}
}
else
{
putchar(*format);
format++;
}
}
}

./a.out
Hello World 100 10.200000 c
-----------------------------------------------------------------------------------
136

JULY 22
STAGES INVOLVED IN COMPILATION
--> Preprocessing (Textual replacement)
--> Compilation (Syntax and Semantic rules checking)
--> Assembly (Generate object file(s))
--> Linking (Resolve linkages)

Preprocessing:

4 Stages:
1. Inclusion of header file

#include<stdio.h>

2. Removing the comments

3. Substitution of MACROS

4. Conditional compilation
--> on some conditions, code will be added or removed

gcc -E file_name.c -o file_name.i

--> gets the header file contents

--> preprocessing will generate a file which is intermediate file with extension
“.i”

at the preprocessing stage, MACROS will be substituted before compilation.

Preprocessor will never throw error for syntax error, it is simply load the header
file, and substitution operation.

Compilation:
gcc -S file_name.c -o file_name.s
Everything is converted to ascii code. .s extention

if editing the file, error may be occur.

gcc -save-temps demo.c

saves all files


137

JULY 23
PREPROCESSOR – DIRECTIVES

• #include
• #define
• #undef
• #ifdef
• #ifndef
• #if
• #elif
• #else
• #endif
• #error
• #warning
• #line
• #pragma
• #
• ##

A header file is a file containing C declarations and macro definitions to be


shared between several source files.

<file.h> //search in standard path, if not found it throws error


“file.h> //first search in local dir. And then in standard path ,if not
found
it will throw the error.

1_file1.c 2_file1.c

#include<stdio.h> char *test(void)


#include "2_file2.c" {
int main() static char *str ="HELLO";
{ return str;
puts(test()); }
return 0;
}

2_file2.c HERE function prototype file is included


as header file.
char *test(void);

gcc 1_file.c 2_file1.c


./a.out
HELLO
In this both can be included function file and prototype file in the header file.

If< > is given for local header file

gcc file_name.c -I. ==> to search in local file

gcc *.c -I. /path/ ==> to compile all files in Dir. to search in the sub-
paths

gcc -E 1_file.c 2_file1.c -I. -P


To see as one file ==> remove unwanted lines
138

char *test(void);
char *test(void)
{
static char *str ="HELLO";
return str;
}
int main()
{
puts(test());
return 0;
}
char *test(void)
{
static char *str ="HELLO";
return str;
}

to view all function prototypes : vi /usr/include/stdio.h

-----------------------------------------------------------------------------------
MACRO

#include<stdio.h>
#define PI 3.14
int main()
{
printf("%f",PI);
}
./a.out
3.140000

PREDEFINED MACROS
#include<stdio.h>
int main()
{
printf("%s\n",__FILE__);
printf("was completed on %s at %s\n",__DATE__, __TIME__);
printf("This print is from function :%s\n",__func__);
//__func__ is small case and substituted only at runtime
//Because function are called and processed during runtime

printf("at line %d\n",__LINE__);


}
./a.out
demo.c
was completed on Jul 27 2021 at 20:10:04
This print is from function :main
at line 7

FUNCTION LIKE MACROS

#include<stdio.h>
#define SET_BIT(num, pos) num | (1 << pos)
139

int main()
{
printf("%d\n", 2 * SET_BIT(0,2));
return 0;
}
gcc -E demo.c -P
int main()
{
printf("%d\n", 2 * 0 | (1 << 2));
return 0;
}

./a.out
4
140

JULY 26
#include<stdio.h>
#define SWAP(a,b) \
int temp = a; \
a = b; \
b=temp; \

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

SWAP (n1,n2);
printf("%d %d\n", n1, n2); //error: redefinition of ‘temp’

return 0;
}
-----------------------------------------------------------------------------------
#include<stdio.h>

#define SWAP(a,b) \ //acts as a function


{ int temp = a; \ //temp is a local variable now
a = b; \
b= temp; \
}
int main()
{
int n1 = 10, n2 =20;
SWAP(n1, n2);
printf("%d %d\n", n1, n2);
SWAP(n1,n2);
printf("%d %d\n", n1, n2);
return 0;
}
./a.out
20 10
10 20
-----------------------------------------------------------------------------------

FUNCTION MACRO

• Context switching overhead • No context switching overhead


• Stack frame creation overhead • No stack frame creation overhead
• Space optimized on repeated call • Time optimized on repeated call
• Compiled at compile stage, invoked • Pre-processed and expanded at
at run time. preprocessing Stage
• Type sensitive • Type insensitive
• Recommended for larger operation • Recommended for smaller operation

-----------------------------------------------------------------------------------
#include<stdio.h>
141

#define WARN_IF(EXP) \
{ \
do{ \
x--; \
if(EX P) \
{ \
fprintf(stderr,"warning :"#EXP "\n"); \
} \
}while(x); \
}
int main()
{
int x = 5;
WARN_IF(x==0);
return 0;
}

./a.out
warning :x==0

#EXP ==> to access as a string


-----------------------------------------------------------------------------------
#include<stdio.h>
#define PRINT(x) x##_val //strcat(x,_val)
int main()
{
int int1_val = 100;
float float1_val = 20.5;
printf("num = %d\n",PRINT(int1));
printf("num2= %f\n",PRINT(float1));
return 0;
}
./a.out
num = 100
num2= 20.500000

PORTABILITY:
It should be able to run on any system, or OS

TESTING:
debug, execution

REFERENCE CODE:
A conditional whose condition is always false is one way to exclude code from
the program but keep it as a sort of comment for future reference.

Demo.c Demo1.c

#include<stdio.h> #ifndef DEMO


#include "demo1.c" #define DEMO
#include "demo1.c" struct user
{
int main() int id;
{ char name[20];
struct user p={420,"hi"}; };
142

return 0; #endif
}

instead of using like if condition, we can use #pragma,


but it is not portable.
gcc -E demo.c demo1.c -P
struct user
{
int id;
char name[20];
};
int main()
{
struct user p={420,"hi"};
return 0;
}
struct user
{
int id;
char name[20];
};

-----------------------------------------------------------------------------------
#include<stdio.h>

=> no matter how many times mentioned, it is included only once because it has a
conditional compilation.
#include<stdio.h> Gcc -E demo.c -P
int main()
#define METHOD1 {
printf("if_part\n");
int main()
{ //only if part is included in compile
#ifdef METHOD1 time
printf("if_part\n");
#else return 0;
printf("else_part\n"); }
#endif
return 0;
}

-----------------------------------------------------------------------------------

#include<stdio.h> Gcc -E demo.c -P


#define METHOD1
int main()
int main() {
{ printf("if_part\n");
#undef METHOD1 return 0;
#ifndef METHOD1 }
printf("if_part\n");
#else
printf("else_part\n");
143

#endif
return 0;
}

#ifdef == #if defined

#include<stdio.h> gcc -E demo.c -P -D METHOD


int main() //to include at compile time -D
{ int main()
#ifdef METHOD {
printf("if_part\n"); printf("if_part\n");
#else return 0;
printf("else_part\n"); }
#endif
return 0;
}

for commenting

#if 0
/*
statements are commented

*/
endif
-----------------------------------------------------------------------------------
#warning
#error

can be user made like the compiler

#include <stdio.h>

#if defined DEBUG_PRINT //NOT DEFINED


#warning “Debug print enabled”
#endif

int main()
{
int sum, num1, num2;
printf("Enter 2 numbers: ");
scanf("%d %d", &num1, &num2);
#ifdef DEBUG_PRINT //not included
printf("The entered values are %d %d\n", num1, num2);
#endif
sum = num1 + num2;
printf("The sum is %d\n", sum);
return 0;
}

gcc -E demo.c -P
int main()
{
int sum, num1, num2;
144

printf("Enter 2 numbers: ");


scanf("%d %d", &num1, &num2);
printf("The entered values are %d %d\n", num1, num2);
sum = num1 + num2;
printf("The sum is %d\n", sum);
return 0;
}
-----------------------------------------------------------------------------------

#include <stdio.h>
int main()
{
#line 100 "project tuntun"
printf("This is from file %s at line %d \n", __FILE__ , __LINE__ );
return 0;
}

./a.out
This is from file project tuntun at line 100
-----------------------------------------------------------------------------------
145

JULY 27 USER DEFINED DATATYPES

Derived with the use of:

• Structure
• Unions
• Typedef
• Enum

Structure:
It is a collection of elements of different / same datatype under one common
name.

Array --> collection of same type of elements

SYNTAX :

struct student
{
int x;
char name[20];
}

==> memory will not be allocated when you create/ define the structure.
Only at the creation of variable memory is allocated

Memory will be allocated continuously.


---------------------------------------------------------------------------------------------------

#include <stdio.h>
struct student
{
int id;
char name[20];
char address[60];
};
int main()
{
struct student s;
146

printf("%zu\n", sizeof(struct student)); //data_type name


printf("%zu\n",sizeof(s)); //variable
return 0;
}
./a.out
84
84
---------------------------------------------------------------------------------------------------
#include <stdio.h>
struct student
{
int id;
char name[20];
char address[60];
};
int main()
{
struct student s;
s.id = 10;
printf("id=%d\n",s.id);
return 0;
}
./a.out
10
---------------------------------------------------------------------------------------------------

#include <stdio.h>
#include<string.h>
struct student
{
int id;
char name[20];
char address[60];
};
int main()
{
struct student s;
strcpy(s.name, "karthi");
printf("name=%s\n",s.name);
return 0;
147

}
./a.out
name=karthi
---------------------------------------------------------------------------------------------------
#include <stdio.h>
#include<string.h>
struct student
{
int id;
char name[20];
char address[60];
};
int main()
{
struct student s = {10,"karthi","sattur"};
printf("s.id == %d\n",s.id);
printf("s.name == %s\n",s.name);
printf("s.address == %s\n",s.address);
return 0;
}
./a.out
s.id == 10
s.name == karthi
s.address == sattur
---------------------------------------------------------------------------------------------------
Structure can be copied by using assignment operator ‘=’

struct student s1={“1, karthi, sattur}, s2;

s2 = s1;

#include <stdio.h>
#include<string.h>
struct student
{
int id;
char name[20];
char address[60];
};
int main()
148

{
struct student s = {10,"karthi","sattur"}, s_new;
printf("s.id == %d\n",s.id);
printf("s.name == %s\n",s.name);
printf("s.address == %s\n",s.address);
s_new = s;
printf("s_new.id == %d\n",s_new.id);
printf("s_new.name == %s\n",s_new.name);
printf("s_new.address == %s\n",s_new.address);
return 0;
}
./a.out
s.id == 10
s.name == karthi
s.address == sattur
s_new.id == 10
s_new.name == karthi
s_new.address == sattur

values are copied but the address remains the same


---------------------------------------------------------------------------------------------------

#include <stdio.h>
#include<string.h>
struct student
{
int id;
char name[20];
char address[60];
};
int main()
{
struct student s = {10,"karthi","sattur"}, s_new;
printf("s.id == %lu\n",&s.id);
printf("s.name == %lu\n",&s.name);
printf("s.address == %lu\n",&s.address);
s_new = s;
printf("s_new.id == %lu\n",&s_new.id);
149

printf("s_new.name == %lu\n",&s_new.name);
printf("s_new.address == %lu\n",&s_new.address);
return 0;
}
./a.out
s.id == 140727055956080
s.name == 140727055956084
s.address == 140727055956104

s_new.id == 140727055956176
s_new.name == 140727055956180
s_new.address == 140727055956200
---------------------------------------------------------------------------------------------------
s is not equal to &s

Structure pointers

struct student s1;

struct student *sptr =&s1; //pointer has size 4/8

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


#include<string.h> #include<string.h>
struct student struct student
{ {
int id; int id;
char name[20]; char name[20];
char address[60]; char address[60];
}; };
static struct student s; static struct student s;
int main() int main()
{ {
struct student *ptr = &s; struct student *ptr = &s;
ptr->id=10; (*ptr).id=10;
printf("%d\n",ptr->id); printf("%d\n",(*ptr).id);
return 0; return 0;
} }
./a.out
150

10
*ptr.id will throw error as “.” is executed first

Function structure
Structure can be passed to a function and can be returned.

If passed as pass by value, it will be taking more space.

If pointer is passed, it takes only small space in stack.


151

JULY 28

struct Student //structure definition & initialisation


{
int id;
char *name;
char *address;
}

struct Student data(void) //allocating memory in heap


{
struct Student s;
s.name = (char *) malloc(30 * sizeof(char));
s.address = (char *) malloc(150 * sizeof(char));
return s;
}

int main()
{
struct student s1;
s1 =data(); //returning structure can be asssigned to another
s1.name(free);
s1.address(free);
return 0;
}

-----------------------------------------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
struct Student
{
int id;
char *name;
char *address;
};

struct Student data(void)


{
struct Student s;
s.name = (char *) malloc(30 * sizeof(char));
s.address = (char *) malloc(150 * sizeof(char));
return s;
};

int main()
{
struct Student s[2];
s[0] = data();
s[1] = data();
int i;
printf("ENTER THE 2 STUDENT DETAILS\n");
for(i = 0; i < 2; i++)
scanf("%d %s %s", &s[i].id, s[i].name, s[i].address);

printf("\nTHE DETAILS OF THE 2 STUDENTS ARE\n");


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

printf("\ns[%d].id is %d\ns[%d].name is %s\ns[%d].address is %s\n", i,


s[i].id, i, s[i].name, i, s[i].address);

return 0;
}

./a.out
ENTER THE 2 STUDENT DETAILS
32
karthi
sattur
234
jagajeevan
tanjore

THE DETAILS OF THE 2 STUDENTS ARE

s[0].id is 32
s[0].name is karthi
s[0].address is sattur

s[1].id is 234
s[1].name is jagajeevan
s[1].address is tanjore

-----------------------------------------------------------------------------------
//anonymous structure
struct
{
int id;
char name[30];
char address[50];
}s1;

it can be any number of variables, but creating a new structure variable is not
possible.

{
}s1,s2,s3;
-----------------------------------------------------------------------------------
STRUCTURE WITHIN STRUCTURE

#include<stdio.h>
#include<stdlib.h>
struct College
{
struct Student
{
int id;
char name[30];
char address[50];
}student;
struct //no name only variable
{
int id;
char name[30];
char address[50];
153

}faculty;
};

int main()
{
struct College member;

struct Student s; //possible


struct faculty f; //error

member.student.id = 20;
member.faculty.id = 30;
return 0;
}
-----------------------------------------------------------------------------------
STRUCTURE PADDING

Compiler will add useless bytes in between members of structure.

#include<stdio.h>
#include<stdlib.h>
struct Student
{
char ch; 1+4+1=6 ,but the answer is 12
int id;
char name;
};

int main()
{
struct Student s;
printf("%zu\n",sizeof(struct Student));
printf("%zu\n",sizeof(s));
return 0;
}

./a.out
12
12

-----------------------------------------------------------------------------------
disk fragmentation --> arrange data in a straight line

word size – 4 in 32 bit


- 8 in 64 bit

For character fetching in 32 bit system it is done in word size (i.e 4bytes), but
it will discard 3 bytes and give the one byte for us.

PADDING IS DONE ON THE FOLLOWING POINTS:


1. Based on the member arrangement.
2. Based on the largest member size.
3. Based on word size.
154

#include<stdio.h>
#include<stdlib.h>
struct Student
{
char ch;
char name;
int id;
};

int main()
{
struct Student s;
printf("%zu\n",sizeof(s));
return 0;
}
./a.out
8
-----------------------------------------------------------------------------------
=#include<stdio.h>
#include<stdlib.h>
struct Student
{
char ch;
char name;
double id;
};

int main()
{
struct Student s;
printf("%zu\n",sizeof(s));
return 0;
}
./a.out
8
./a.out
16
-----------------------------------------------------------------------------------
155

JULY 29
#include<stdio.h>
#include<stdlib.h>
#pragma pack(1) //pack(2 power values)
struct Student
{
char ch; //allocating 1 byte at a time
int id;
char name;

};

int main()
{
struct Student s;
printf("%zu\n",sizeof(s));
return 0;
}
./a.out
6
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
#pragma pack(2) //pack(2 power values)
struct Student
{
char ch; //allocate 2 bytes at a time
int id;
char name;

};

int main()
{
struct Student s;
printf("%zu\n",sizeof(s));
return 0;
}
./a.out
8
-----------------------------------------------------------------------------------
if not 2 power values, it will throw a warning, and ignore the pragma.

1 to 4 is allowed, above that it is not useful.

To access and assigning in bit wise, use of BIT FIELDS is recommended in structure
and unions.

-----------------------------------------------------------------------------------
156

#include<stdio.h>
#include<stdlib.h>
struct Nibble
{
unsigned char lower : 4; //4bits
unsigned char upper : 4; //4bits
};
int main()
{
struct Nibble nibble;
nibble.upper = 0x0A;
nibble.lower = 0x02;
printf("%x\n",nibble.lower);
printf("%x\n",nibble.upper);
return 0;
}
./a.out
2
a
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
struct Nibble
{
unsigned char lower : 4;
unsigned char upper : 6; //6bits will be treated padding
};
int main()
{
struct Nibble nibble;
printf("%zu\n",sizeof(nibble));
}
./a.out
2
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
struct Nibble
{
unsigned char lower : 4;
unsigned char upper : 9;
};
int main()
{
struct Nibble nibble;
printf("%zu\n",sizeof(nibble));
}
error: width of ‘upper’ exceeds its type
-----------------------------------------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
struct Nibble
{
char lower : 4;
157

char upper : 4;
};
int main()
{
struct Nibble nibble;
nibble.upper = 0x0A;
nibble.lower = 0x02;
printf("%x\n",nibble.lower);
printf("%x\n",nibble.upper);
return 0;
}
./a.out
2
fffffffa

lower nibble has no problem in signed char.


but the upper is treated as negative number resulting in taking 2s compliment
-----------------------------------------------------------------------------------
UNIONS

The major difference between union and structure is that structure members get
different memory allocation, and in case of unions there will be memory allocation
for the biggest data type.

#include<stdio.h>
#include<stdlib.h>
union Test
{
char option;
int id;
double height;
};
int main()
{
union Test temp;
printf("Size = %zu\n",sizeof(temp));
temp.height = 7.2;
temp.id = 0x1234;
temp.option = '1';
printf("%lf\n",temp.height);
printf("%d\n",temp.id);
printf("%c\n",temp.option);
return 0;
}

./a.out
Size = 8
7.199997
4657
1

THE UNION VARIABLES SHARES THE SAME SPACE AND IT IS MODIFIED CONTINUOUSLY WHILE
ASSIGNING NEW VALUES.
-----------------------------------------------------------------------------------
158

#include<stdio.h>
#include<stdlib.h>
union Floatbits
{
float degree;
struct
{
unsigned m : 23;
unsigned e :8;
unsigned s :1;
}elements;
};
int main()
{
union Floatbits fb = {3.2};
printf("Sign :%X\n",fb.elements.s);
printf("Exponent : %X\n",fb.elements.e);
printf("Mantissa :%X\n",fb.elements.m);
return 0;
}
/a.out
Sign :0
Exponent : 80
Mantissa :4CCCCD
-----------------------------------------------------------------------------------
159

JULY 30
Typedef --> another name for variable, function pointers

to change the data type of a variable.

Reasons for using a typedef

--> only a single typedef statement has to be changed to change the


type of the variable, making it more portable.

--> easier to understand a complex definition or declaration.


---------------------------------------------------------------------
typedef unsigned int data_type;
intmain()
{
data_type number;
return 0;
}
---------------------------------------------------------------------

typedef int * int_ptr; //int * can be replaced by int_ptr


typedef float * float_ptr;
int main()
{
int_ptr ptr1, ptr2, ptr3;
float_ptr fptr;
return 0;
}
---------------------------------------------------------------------

typedef int array_of_100[100];


int main()
{
array_of_100 array;
printf(“%zu\n”,sizeof(array));
return 0;
}
./a.out
400
---------------------------------------------------------------------
160

FOR STRUCTURE
typedef struct _Student
{
int id;
char name[30];
char address[150]
} Student;
void data(Student s)
{
s.id = 10;
}
int main()
{
Student s1;
data(s1);
return 0;
}
---------------------------------------------------------------------
FOR FUNCTION POINTER
#include <stdio.h>
typedef int (*fptr)(int, int);
int add(int num1, int num2)
{
return num1 + num2;
}

int main()
{
fptr function;
function = add;
printf(“%d\n”, function(2, 4));
return 0;
}
---------------------------------------------------------------------
MORE THAN ONE ALIAS NAME CAN BE USED

typedef signed int sint, si;


STANDARAD TYPEDEFS

size_t – stdio.h
ssize_t – stdio.h
va_list – stdarg.h

---------------------------------------------------------------------
161

#include<stdio.h>
typedef struct Sensor
{
int id;
char name[12];
int version;
union
{
float temp;
float humidity;
char motion[4];
};
}Sensor;

int main()
{
printf("%zu\n",sizeof(Sensor));
return 0;
}
./a.out
24
---------------------------------------------------------------------
ENUMS

#include<stdio.h>
enum bool
{
e_false,e_true //self assign starting from 1
};
int main()
{
printf("%d\n",e_false);
printf("%d\n",e_true);
}
./a.out
0
1
---------------------------------------------------------------------
#include<stdio.h>
enum bool //global scope
{
e_false, e_true //self assign starting from 1
};
int main()
{
enum bool e_extra1,e_extra2;
printf("%d\n",e_false);
162

printf("%d\n",e_true);
printf("%d\n",e_extra1);
printf("%d\n",e_extra2);
}
./a.out
10
90
0 //garbage
0 //garbage
---------------------------------------------------------------------
#include<stdio.h>
enum bool
{
e_false, e_true=90, //self assign starting from 1
e_extra1,e_extra2 //continues from 91
};
int main()
{
printf("%d\n",e_false);
printf("%d\n",e_true);
printf("%d\n",e_extra1);
printf("%d\n",e_extra2);
}
./a.out
0
90
91
92
---------------------------------------------------------------------
#include<stdio.h>
typedef enum
{
e_red = 1,
e_ble = 4,
e_green
}color;
int main()
{
color e_white =0, e_black;
printf("%d\n",e_white);
printf("%d\n",e_black);
printf("%d\n",e_green);
}
./a.out
0
0 //garbage, no continuation in main
5
163

---------------------------------------------------------------------
164

Aug 2

FILE *fp;
Operations on the files can be
--open
--file operations
--close

To open a file

FILE *fopen(const char *path, const char *mode);

*path --> name of a file/ file along with the path


“text.txt”, “/usr/desktop/text.txt”, “c:/folder/text.txt”

*mode --> mode of file

“r” mode --> read mode


--> can only read information from a file/ only read operation
--> If file exists, then it will open the file
Else return a NULL
--> If success --> returned pointer will points to first character
of the file.

“w” mode --> write mode


--> only write operation
--> If file exists, then it will open the file and write the info.
Else it will create a new file
--> If success --> If already file contains the info, then write
mode will replace the previous contents with
new contents.
--> File pointer will points to the first character of the file.

“a” mode --> append mode


--> If the file exists, then it will open the file and add the info
Else it will create a new file.
--> If success --> If already file contains the info then append
mode concat or add the previous contents with
new contents.

--> File pointer will points to last character of the file.

“r+” mode --> read and write mode


--> both read and write operation
--> If file exists it open the file else it will return NULL

“w+” mode --> write and read mode


--> write and read operation
--> If file exists open the file , else create a new file.

“a+” mode --> read+write


--> new content will be concatenated with previous.
--> pointer points to last character.

FILE NOT EXISTS


#include <stdio.h>
165

int main()
{
FILE *fp;
fp = fopen("test.txt","r"); ==>read mode
fclose(fp);
return 0;
}
segmentation fault

#include <stdio.h>
int main()
{
FILE *fp;
fp = fopen("test.txt","w"); ==>no error in write mode
fclose(fp);
return 0;
}

#include <stdio.h>
int main()
{
FILE *fp;
fp = fopen("test1.txt","r");
if(fp == NULL)
{
printf("FILE DOESN'T EXISTS\n");
return 1;
}
fclose(fp);
return 0;
}
./a.out
FILE DOESN'T EXISTS
-----------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
FILE *fp;
char ch;
fp = fopen("test.txt","r");
if(fp == NULL)
{
printf("FILE DOESN'T EXISTS\n");
return 1;
}
else
{
while(ch = fgetc(fp))
{
if(feof(fp))
break;
fputc(ch, stdout);
}
}
fclose(fp);
return 0;
166

}
./a.out
ABCDEFGH
-----------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
FILE *fp, *fcpy;
char ch;
fp = fopen("test.txt","r");
fcpy = fopen("test_copy.txt", "w");
if(fp == NULL)
{
printf("FILE DOESN'T EXISTS\n");
return 1;
}
else
{
while(ch = fgetc(fp))
{
if(feof(fp))
break;
fputc(ch, fcpy);
}
}
fclose(fp);
return 0;
}

test.txt
ABCDEFGH karthikeyan

test_copy.txt
ABCDEFGH karthikeyan
-----------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
FILE *fp, *fcpy;
char ch;
fp = fopen("test.txt","w");
ch = fgetc(fp);
if(ferror(fp))
fprintf(stderr, "Error in reading from file test.txt\n");
fclose(fp);
return 0;
}
./a.out
Error in reading from file test.txt
-----------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
FILE *fp, *fcpy;
char ch;
fp = fopen("test.txt","w");
ch = fgetc(fp);
167

if(ferror(fp))
fprintf(stderr, "Error in reading from file test.txt\n");
clearerr(fp);
if(ferror(fp))
fprintf(stderr, "Error in reading from file test.txt\n");
fclose(fp);
return 0;
}
./a.out
Error in reading from file test.txt
-----------------------------------------------------------------------------------
ftell( FILE *) --> Provide some info/ convey the msg
--> it will give information about where the file pointer is
pointing.
--> fptr position will always be starting 0

#include <stdio.h>
int main()
{
FILE *fp, *fcpy;
char ch;
fp = fopen("test.txt","r");

if(fp == NULL)
return 1;
while ((ch = fgetc(fp)) != EOF)
{
if(ch == 'c')
printf("c is at --> %ld\n",ftell(fp));
}
fclose(fp);
return 0;
}

test.txt
ckartccckekc

./a.out
c is at --> 1
c is at --> 6
c is at --> 7
c is at --> 8
c is at --> 12.
-----------------------------------------------------------------------------------
rewind() --> to get the pointer point to the starting position.

AUG 3

fseek --> function which make file pointer to print anywhere in the file

syntax

fseek(FILE *, how much need to move, from where);

how much need to move --> 0L (long value), 10L, -10l.


168

from where --> SEEK_SET --> file pointer will start from beginning of file
--> SEEK_END --> file pointer will be set to end of the file
--> SEEK_CUR --> file pointer will move from current position

fseek(fptr, 5L, SEEK_SET); fptr will move 5 bytes from start

fseek(fptr, -5L, SEEK_END); fptr will move 5 bytes from back

fseek(fptr, 0L, SEEK_SET) ==> rewind(fptr) //same operation

syntax for fwrite:


size_t fwrite( const void *ptr, size_t size, size_t nitems, FILE *stream);

fwrite will give the size of file as number of characters while, fprintf will give
the size of datatypes added.
-----------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
int num1, num2;
int num3, num4;
FILE *fptr, *fptr1;

if(( fptr = fopen("text2.txt","w+")) == NULL)


{
fprintf(stderr,"Can't open input file text2.txt!\n:");
return 1;
}
scanf("%d%d", &num1, &num2);
fwrite(&num1, sizeof(num1), 1, fptr);
fwrite(&num2, sizeof(num2), 1, fptr);
fclose(fptr);
}
-rw-rw-r-- 1 karthi karthi 8 Aug 6 08:25 text2.txt
-----------------------------------------------------------------------------------
#define _GNU_SOURCE //for fcloseall
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv)
{
FILE *fp, *fp1;
char *ptr = argv[1];
fp = fopen(ptr, argv[2]);
fcloseall();
return 0;
}
./a.out test.txt w //test.txt will be opened in “w” mode
VOLATILE --> making variables not subjective to optimization

You might also like