SlideShare a Scribd company logo
1.8. STRINGS 151
✞
Type ’e’ for encrypt & ’d’ for decrypt : e
✌
✆
✞
Type ’e’ for encrypt & ’d’ for decrypt : f
Unknown procedure .
✌
✆
strcpy
This function copies the string from source into destination. The size of the destination
object shall be sufficiently large to hold the source string. If size of destination object is
deficient of space, an overflow error occurs. The syntax of strcpy() is
✞
char *strcpy(char *restrict dest , 
2 const char *restrict src);
✌
✆
Note, source of strcpy should be string. It is recommended that strncpy() should be used
instead of strcpy(), to avoid buffer overflow. A simple example is
✞
#include <stdio.h>
2 #include <string.h>
4 int main () {
/* initialize a char variable */
6 char str [80];
/* copy string The to variable .*/
8 strcpy(str , "The ");
/* concate the string India with The */
10 strcat(str , "India ");
strcat(str , "is ");
12 strcat(str , "developing .");
/* put output at the console */
14 puts (str);
return 0;
16 }
✌
✆
✞
The India is developing .
✌
✆
An example which copies the contents of one array into other array without using strcpy()
function is given below. In this example, one by one character of array ‘strA’ are copied
into array ‘strB’. When array ‘strA’ encounters the null character, copying is halted.
✞
1 #include <stdio.h>
3 int main () {
char strA [50], strB [50];
5 int i;
printf("nEnter string s1: ");
7 scanf("%s", strA );
/* Copy one by one character into strB .*/
152 Basic C
9 for (i = 0; strA [i] != ’0’; i++) {
strB [i] = strA [i];
11 }
/* Add null character to strB at the end.*/
13 strB [i] = ’0’;
printf("nString s2: %s", strB );
15 return 0;
}
✌
✆
Following is a strcpy() example that is used to trim the white spaces from the left and
right hand side of a string.
✞
#include <stdio.h>
2 #include <string.h>
#include <ctype.h>
4
/* Trimming leading and trailing white spaces. */
6 char *trim (char * s) {
/* Initialize start , end pointers */
8 char *s1 = s, *s2 = &s[strlen(s) - 1];
10 /* If last char is a white space and there*
* is a previous char that is also a white*
12 * space then reduce the pointer by one *
* for each white space. */
14 while (( isspace (*s2)) && (s2 >= s1))
s2 --;
16 /* Finally we find the pointer value for *
* last character other than a white space.*/
18
/* Add end of line . */
20 *(s2 + 1) = ’0’;
22 /* If first char is a white space and there*
* is next char that is also a white space *
24 * then increase the pointer position by *
* one for each white space. */
26 while (( isspace (*s1)) && (s1 < s2))
s1 ++;
28
/* Copy rest of string to s */
30 strcpy(s, s1);
return s;
32 }
34 int main (int argc , char *argv [ ]) {
char *s;
36 char string [100] = " 1arun2 ";
printf("The original string is :%s:n", string);
38 s = trim (string);
printf("The trimmed string is :%s:n", s);
1.8. STRINGS 153
40 return 0;
}
✌
✆
✞
The original string is : 1arun 2 :
The trimmed string is :1 arun 2:
✌
✆
strlen
Synopsis of strlen() function is
✞
size _t strlen(const char *s);
✌
✆
The strlen() function shall compute the number of bytes in the string to which ‘s’ points,
not including the terminating null byte. It returns the number of bytes in the string. No
value is used to indicate an error. A simple example is
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 char Input [256];
printf("Enter a string : ");
7 gets ( Input);
printf("The string length is %u characters long .n",
9 (unsigned ) strlen(Input));
return 0;
11 }
✌
✆
✞
Enter a string : a
The string length is 1 characters long .
✌
✆
strlen() counts only those cells in which string or character is stored. The counting of
strlen() is stopped when, it encountered the cell of null character. We can used several
methods to find the string length without using strlen function.
✞
#include <stdio.h>
2 #include <stdlib.h>
4 int main (void ) {
int n = 0, c;
6 /* get string to be counted */
printf("Enter the string : ");
8 while ((c = getchar ()) != ’n’) {
n++;
10 }
printf("The string length is %d.n", n);
12 return 0;
}
✌
✆
154 Basic C
✞
Enter the string : arun kumar
The string length is 10.
✌
✆
A new example that uses array and strlen() function to get reverse of the supplied string.
Actually in this example, strlen() function is used to get the length of the string. After
that the characters of the string are printed in reverse order.
✞
#include <stdio.h>
2 #include <stdlib.h>
4 int main (void ) {
char rs [1000]; // string to reversed .
6 /* get string to be reversed */
printf("Enter the string to be reversed : ");
8 scanf("%s", rs);
printf("The reversed string is : ");
10 /* While array is not triggered with space*/
int n = strlen(rs);
12 while (n > 0) {
printf("%c", rs[n - 1]);
14 n--;
}
16 return 0;
}
✌
✆
✞
Enter the string to be reversed : arun
The reversed string is : nura
✌
✆
In following example, classical method is used to find the length of a string. In this
example, we count the characters in a string until a null terminating character is not
obtained. After each counting, counter is increased by one. At last the counting value is
the actual length of the string.
✞
#include <stdio.h>
2
int main (void ) {
4 char name [ ] = "NAME arun kr";
int i = 0;
6 while (name [i] != NULL )
i++;
8 printf("The length of string "%s" is %d.", name , i);
return 0;
10 }
✌
✆
✞
The length of string "NAME arun kr" is 12.
✌
✆
The following example is rewritten in which string pointer is passed to a function where
string length is computed. The string length is returned to the main function and printed
in output console.
1.8. STRINGS 155
✞
1 #include <stdio.h>
3 int StrLen(char * str) {
int i = 0;
5 while (str[i] != ’0 ’) {
i++;
7 }
return i;
9 }
11 int main () {
char str[ ] = "This is my string.";
13 int i;
i = StrLen(str);
15 printf("The length of string is %d.n", i);
return 0;
17 }
✌
✆
✞
The length of string is 18.
✌
✆
The memory used by given string may also be retrieve by using keyword ‘sizeof’ as shown
in example below.
✞
1 #include <stdio.h>
#include <string.h> /* provides strlen () prototype */
3 #define PRAISE "Hi!"
5 int main (void ) {
char name [40];
7 printf("What ’s your name ?n");
scanf("%s", name );
9 printf("Hello , %s. %sn", name , PRAISE);
printf("Name has %d letters & occupies %d memory cells.n",
11 strlen(name ), sizeof name );
printf("The praise has %d letters ",strlen(PRAISE));
13 printf("and occupies %d memory cells.n", sizeof PRAISE);
return 0;
15 }
✌
✆
✞
What ’s your name ?
Arun
Hello , Arun . Hi!
Name has 4 letters & occupies 40 memory cells.
The praise has 3 letters and occupies 4 memory cells.
✌
✆
strncat
strncat() function concatenate specific number of characters into destination from the
source. Synopsis of this function is
156 Basic C
✞
1 char *strncat (char *s1 , const char *s2 , size_t n);
✌
✆
The strncat() function shall not append more than ‘n’ bytes. A simple example is
✞
1 #include <stdio.h>
3 int main () {
char str1 [20];
5 char str2 [20];
7 strcpy(str1 , "Hello");
strcpy(str2 , "Worlddddddddd ");
9
printf("Concatenated string is : %sn", strncat (str1 , str2 , 4));
11 printf("Final string is : %sn", str1 );
13 return 0;
}
✌
✆
✞
Concatenated string is : HelloWorl
Final string is : HelloWorl
✌
✆
strncmp
The strncmp function syntax is
✞
int strncmp (const char *s1 , const char *s2 , size_t n);
✌
✆
The strncmp() function shall compare not more than n bytes (bytes that follow a null
byte are not compared) from the array pointed-by ‘s1’ into the array pointed-by ‘s2’. The
sign of a non-zero return value is determined by the sign of the difference between the
values of the first pair of bytes (both interpreted as type unsigned char) that differ in
the strings being compared. See strcmp() for an explanation of the return value. This
function is as useful in comparisons, as the strcmp function is. A simple example is
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 if (strncmp ("arun ", "Arun ", 2) ==0) {
printf("Two strings are equal.");
7 } else {
printf("Two strings are not equal.");
9 }
return (0);
11 }
✌
✆
✞
Two strings are not equal.
✌
✆
1.8. STRINGS 157
strncpy
The syntax of strncpy() function is
✞
1 char *strncpy (char *s1 , const char *s2 , size_t n);
✌
✆
The strncpy() function shall copy not more than ‘n’ bytes (bytes that follow a null byte
are not copied) from the array pointed-by ‘s2’ into the array pointed-by ‘s1’. A simple
example is
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 /* initialize an experimental string */
char str[ ] = "This is a simple string";
7 char * pch;
/* get first occurace of simple*/
9 pch = strstr(str , " simple");
/* copy NAGPUR from the point of simple upto two places.*/
11 strncpy (pch , "NAGPUR", 2);
/* copy NAGPUR from the point of simple upto four places.*/
13 strncpy (pch , "NAGPUR", 4);
puts (str);
15 /* copy NAGPUR from the point of simple upto six places.*/
strncpy (pch , "NAGPUR", 6);
17 puts (str);
return 0;
19 }
✌
✆
✞
This is a NAmple string
This is a NAGPle string
This is a NAGPUR string
✌
✆
In the above program, line
✞
1 strncpy(pch , "NAGPUR", 2);
✌
✆
copied first two characters from the “NAGPUR” at 11th
and 12th
place of the string ‘str’
as shown below:
strncpy(pch, “NAGPUR”, 2)
s i m p l e s
N A G P U R 0
Similarly, in the above program, line
✞
1 strncpy(pch , "NAGPUR", 6);
✌
✆
158 Basic C
copied first six characters from the “NAGPUR” into ‘str’ from 11th
to 16th
place of the
string ‘str’ as shown below:
strncpy(pch, “NAGPUR”, 6)
s i m p l e s
N A G P U R 0
During the copying of strings, size of strings should be clearly defined, otherwise the
actual string may terminate shortly as null terminator is added within the actual string
as shown in the following example.
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 /* initialize an experimental string */
char str[ ] = "This is a simple string";
7 char * pch;
/* get first occurace of simple*/
9 pch = strstr(str , " simple");
/* copy NAGPUR from the point of simple upto seven places.*/
11 strncpy (pch , "NAGPUR", 7);
puts (str);
13 return 0;
}
✌
✆
✞
This is a NAGPUR
✌
✆
strncpy(pch, “NAGPUR”, 7)
s i m p l e s
N A G P U R 0
strrchr
The strrchr() function searches string for the last occurrence of a character. The null
character that represents to the termination of string, is also included in the search. The
prototype of strrchr() function is
✞
1 char *strrchr (const char *s, int c);
✌
✆
strrchr is similar to strchr(), except the string is searched right to left. A simple example
is
1.8. STRINGS 159
✞
1 #include <stdio.h>
3 int main () {
char *s;
5 char buf [ ] = "This is a testing ";
7 s = strrchr (buf , ’t’);
9 if (s != NULL )
printf("found a ’t’ at %sn", s);
11
return 0;
13 }
✌
✆
✞
found a ’t’ at ting
✌
✆
Here is another example that returns the position in a string where a delimiter is found.
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 char str[ ] = "This is my string";
char match[ ] = "i";
7 int i;
int c = 0;
9 for (i = 0; i < strlen(str); i++) {
if (str[i] == match[c] && c < strlen(match)) {
11 c++;
} else {
13 c = 0;
}
15 if (c == strlen(match)) {
printf("Pattern matched after %d charsn",
17 i - strlen(match) + 1);
}
19 }
return 0;
21 }
✌
✆
✞
Pattern matched after 2 chars
Pattern matched after 5 chars
Pattern matched after 14 chars
✌
✆
strstr
The syntax of strstr() function is
160 Basic C
✞
1 char *strstr(const char *string , const char *sub -str);
✌
✆
The strstr() function shall locate the first occurrence in the string pointed-by ‘string’
of the sequence of bytes (excluding the terminating null byte) in the string pointed-by
‘sub-str’. It returns the pointer (or may say the address) of the first occurrence of the
sub-string. A simple example is
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 /* initialize an experimental string */
char str[ ] = "This is a simple string";
7 char * pch;
/* get first occurance of simple */
9 pch = strstr(str , " simple");
puts (pch);
11 return 0;
}
✌
✆
✞
simple string
✌
✆
pch = strstr(str, ”simple”);
T h i s i s a s i m p l e s t r i n g 0
pch s i m p l e s t r i n g 0
strtok
The syntax of strtok function is
✞
1 char *strtok(char *restrict s1 , const char *restrict delimiters );
✌
✆
A sequence of calls to strtok() breaks the string pointed-by ‘s1’ into a sequence of tokens,
each of which is delimited by a byte from the string pointed-by delimiters. This function
returns the address of memory location where tokenised string is stored. first cA simple
example is
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 /* experimental string */
char str[ ] = "- This is my country .";
1.8. STRINGS 161
7 /* pointer for string tokenization */
char * pch;/*Do not need memory allocation , as it*
9 *has to point the memory address *
*being returned by strtok function . */
11 printf("String "%s" is splitted into tokens:n", str);
/* break experimental string with *
13 * spacecomma dot and doublequote */
pch = strtok(str , " ,.-");
15 while (pch != NULL ) {
printf("%sn", pch);
17 pch = strtok(NULL , " ,.-");
}
19 return 0;
}
✌
✆
✞
String "- This is my country ." is splitted into into tokens:
This
is
my
country
✌
✆
Here is an example which splits the string by a delimiter without using strtok() function.
In this example, a string is read character by character and when a read character is equal
to the delimiter, a new line is started.
✞
1 #include <stdio.h>
3 int main (int argc , char *argv [ ]) {
if (argv [1] == NULL ) {
5 printf("Use <utility .exe > <string in double quote >
<delimiter >.n");
exit (0);
7 }
/* get the commandline string*/
9 char *Str = argv [1];
char *Del = argv [2];
11 printf("The delimiter is ’%s ’.n", Del);
printf("The broken strings are : nn", Del);
13 int i = 0;
while (Str[i] != NULL ) {
15 if (Str[i] == Del [0]) {
printf("n");
17 i++;
}
19 printf("%c", Str[i]);
i++;
21 }
printf("nnThe length of string supplied is %d.n", i);
23 return 0;
}
✌
✆
162 Basic C
✞
executable .exe "This is my name " " "
This
is
my
name
The length of string supplied is 15.
✌
✆
strtod
The strtod(), strtof (), and strtold() functions convert the initial portion of the string
pointed-by pointer to double, float, and long double representation, respectively. The
return value is numerical value and pointer stores the rest of string.
✞
1 #include <stdio.h>
#include <stdlib.h>
3
int main () {
5 char str [30] = "20.30300 Rs are spent.";
char *ptr;
7 double ret;
9 ret = strtod(str , &ptr);
printf("The Rs in ( double) is %lfn", ret);
11 printf("|%s|n", ptr);
13 return (0);
}
✌
✆
✞
The Rs in (double) is 20.303000
| Rs are spent.|
✌
✆
1.9 Function
Function in C a group of statements and expressions which accepts inputs, analyse them
according to the statements and expressions, and return the result.
✞
int sum(int a, int b){
2 <function body expressions >
}
✌
✆
A function is like a black box. It takes inputs and do something and throws an output.
A function may be declared with or without definition as shown below:
✞
1 int myFunc (); // Function declared without definition
int myFunc (){} // Function declared with definition
✌
✆
1.9. FUNCTION 163
1.9.1 Function Arguments
A functions accepts inputs through its arguments. A function with two arguments (or
parameters) is defined as
✞
int sum(int a, int b);
✌
✆
These parameters in a function definition are called formal arguments. Here, int a, int b
are known as formal arguments. During the defining of a function, each argument must
be identified by its type. For example, to supply two integer arguments to a function, it
shall be defined like
✞
1 int sum(int a, int b);
✌
✆
while, the definition of function as given below is illegal.
✞
1 int sum(int a, b);// Illegal definition
✌
✆
Here, second argument ‘b’ is type unidentified. A function can be called from anywhere
by supplying actual arguments. The supplied argument to a function are type casted
according to the type of the function argument. For example, when a function type
✞
1 int sum(int a, int b);
✌
✆
is called as
✞
1 sum (2.5, 2);
✌
✆
then the function accepts argument value (or actual arguments) 2.5 as a = 2 because, ar-
gument a is an integer type and supplied argument is float type. While, b = 2. Therefore,
decimal part of the float value is truncated. See example below.
✞
1 #include <stdio.h>
3 /* Sum function with formal arguments */
int sum(int a, int b) {
5 int f;
f = a + b;
7 return f;
}
9
int main (int argc , char *argv [ ]) {
11 int g;
/* Sum function with actual arguments */
13 g = sum (2.5, 2);
printf("Sum of %f and %d is %dn", 2.5, 2, g);
15 return 0;
}
✌
✆
✞
Sum of 2.5 and 2 is 4
✌
✆
164 Basic C
Two dimensional arrays of integer type may also be passed as function argument. Two
dimensional, integer type and static size array is passed to function as shown below:
✞
1 #include <stdio.h>
3 void myFunc(int myArray [3][3]) {
int i, j;
5 for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
7 printf("%d t", myArray[i][j]);
}
9 printf("n");
}
11 }
13 int main () {
int myArray [][3] = {
15 {1, 2, 3},
{4, 5, 6},
17 {7, 8, 9}
};
19 myFunc(myArray);
return 0;
21 }
✌
✆
✞
1 2 3
4 5 6
7 8 9
✌
✆
If height of the two dimensional array is dynamic and only width is fixed then two
dimensional integer type array is passed to a function. The unknown dimension of the
array should be passed to the function as its another parameter.
✞
1 #include <stdio.h>
3 void myFunc(int myArray [][3] , int m) {
int i, j;
5 for (i = 0; i < m; i++) {
for (j = 0; j < 3; j++) {
7 printf("%d t", myArray[i][j]);
}
9 printf("n");
}
11 }
13 int main () {
int myArray [3][3] = {
15 {1, 2, 3},
{4, 5, 6},
17 {7, 8, 9}
};
1.9. FUNCTION 165
19 myFunc(myArray , 3);
return 0;
21 }
✌
✆
✞
1 2 3
4 5 6
7 8 9
✌
✆
A dynamic two dimensional integer type array may passed to a function as its argument
in pointer form. Remember that as two dimensional array passed to function a pointer
only and the called function does not know the actual size of the passed array. Therefore,
dimensions of the array must be passed as another parameters of the function.
✞
1 #include <stdio.h>
3 /* Catch myArray pointer as parameter of *
* function . myr parameter points to passed*
5 * array as 1D array not as 2D array. */
void myF(int *mAr , int m, int n) {
7 int i, j;
for (i = 0; i < m; i++) {
9 for (j = 0; j < n; j++) {
/* Print the array elements row by row.*/
11 printf("%d ", *(( mAr + i * n) + j));
}
13 printf("n");
}
15 }
17 int main () {
int myArray [][3] = {
19 {4, 5, 6},
{1, 2, 3},
21 {9, 8, 7}
};
23 /* Pass myArray as a pointer. */
myF(( int *) myArray , 3, 3);
25 return 0;
}
✌
✆
✞
4 5 6
1 2 3
9 8 7
✌
✆
166 Basic C
myArray[m][n]= 11 12 13 14 15
21 22 23 24 25
31 32 33 34 35
41 42 43 44 45
51 52 53 54 55
i
j
myF((int *) myArray, ...)
Pass Array to Function
In above example, array is passed as pointer and the address of the array pointer is catches
by the function as its parameter. Notice that, inside the function, array pointer does not
represents to two dimensional array but represents to one dimensional array as a group
of bytes in row by row order. This is why, in this function the dimensions of the array are
passed via two additional parameters. These parameters are used to control the printing
of each element of the passed array.
void myF(int *mAr, ...){...} 11 12 13 14 15 21 22 23 24 25 ...
*((mAr+i*n)+j) *((mAr+i*n)+j)
Array as Argument
Now, again, in C, a function without any argument can be compiled ans run by calling
with any number of arguments. See the example below:
✞
1 #include <stdio.h>
3 void testFun () { } // Function declared without arguments
5 int main (void ){
// Function called with three argument .
7 testFun (10, "x", "Y");
return 0;
9 }
✌
✆
But if the argument of prototype function is void type then the program fails to compile
and run. See below:
✞
1 #include <stdio.h>
3 void testFun (void ) { } // Function declared with void arguments
5 int main (void ){
// Function called with three argument .
7 testFun (10, "x", "Y");
return 0;
9 }
✌
✆
1.9. FUNCTION 167
1.9.2 Function Prototype
The declaration of a function prototype tell the compiler three important things about
it:
1. to expect to encounter them further down the program;
2. the return types of the function, e.g. void, int or double;
3. the number and kind of arguments the function is to handle;
The parameter names listed in a function’s prototype may be same as in the function’s
declaration or not. Function prototype allows to omit the variable name in its arguments.
The legal function prototyping are
✞
1 int sum(int , int); /* Legal prototype .*/
int sum(int a, int b); /* Legal prototype .*/
3 int sum(a, int b); /* Illegal prototype .*/
int sum(int *, int *a); /* Legal prototype with pointer array.*/
5 int sum(int *, int &a); /* Illegal prototype with address of a*/
int sum(int [ ], int a[ ]); /* Legal prototype with array.*/
✌
✆
Function prototyping is required when a function is called from the body of another
function which is defined above the called function. It also needed to be declared if
function is envoked before its definition as shown in the below example.
✞
#include <stdio.h>
2 /* Prototype is required .*/
void swap (int * u, int * v);
4
int main (void ) {
6 int x = 5, y = 10;
printf("Originally x = %d and y = %d.n", x, y);
8 swap (&x, &y); /* Send addresses to function */
printf("Now x = %d and y = %d.n", x, y);
10 return 0;
}
12
void swap (int * u, int * v) {
14 int temp ;
temp = *u; /* temp gets value that u points to */
16 *u = *v; /* Store the value of v at address of x*/
*v = temp ; /* Store the value of u at address of y*/
18 }
✌
✆
✞
Originally x = 5 and y = 10.
Now x = 10 and y = 5.
✌
✆
If prototype is not declared, then the compiler shows errors as in the following example,
function is envoked before the definition of the function.
168 Basic C
✞
#include <stdio.h>
2 /* Prototype is disabled .*/
// void swap (int * u, int * v);
4
int main (void ) {
6 int x = 5, y = 10;
printf("Originally x = %d and y = %d.n", x, y);
8 swap (&x, &y); /* send addresses to function */
printf("Now x = %d and y = %d.n", x, y);
10 return 0;
}
12
void swap (int * u, int * v) {
14 int temp ;
temp = *u; /* temp gets value that u points to */
16 *u = *v; /* Store the value of v at address of x*/
*v = temp ; /* Store the value of u at address of y*/
18 }
✌
✆
Again, if a function is called from the body of another function which is defined below to
the called function, then declaration of prototype is not required.
✞
#include <stdio.h>
2
void swap (int * u, int * v) {
4 int temp ;
temp = *u; /* temp gets value that u points to */
6 *u = *v; /* Store the value of v at address of x*/
*v = temp ; /* Store the value of u at address of y*/
8 }
10 int main (void ) {
int x = 5, y = 10;
12 printf("Originally x = %d and y = %d.n", x, y);
swap (&x, &y); /* send addresses to function */
14 printf("Now x = %d and y = %d.n", x, y);
return 0;
16 }
✌
✆
✞
Originally x = 5 and y = 10.
Now x = 10 and y = 5.
✌
✆
Another point is to be remembered that C compiler assumes a function as integer return
type by default. If user defined function is declared as integer type, then C compiler does
not failed to compile a function without prototype declaration. If user defined function
returns other values then compiler fails to compile the program. The following example
compiled successfully.
✞
#include <stdio.h>
2 /* Declaring prototype */
1.9. FUNCTION 169
char myFunc ();
4
int main (void ) {
6 /* Calling function of integer type return.*/
printf("Calling function myFunc()n");
8 printf("Returned value is %c", myFunc ());
return 0;
10 }
12 /* Declaring function of char type return.*/
char myFunc () {
14 return ’A’;
}
✌
✆
✞
Calling function myFunc ()
Returned value is A
✌
✆
Above function is re-written without declaring prototype. This program is failed to
compile.
✞
#include <stdio.h>
2
int main (void ) {
4 /* Calling function of integer type return.*/
printf("Calling function myFunc()n");
6 printf("Returned value is %c", myFunc ());
return 0;
8 }
10 /* Declaring function of char type return.*/
char myFunc () {
12 return ’A’;
}
✌
✆
There is no problem if the function is declared with integer return type. See the example
below which is modified form of above function.
✞
1 #include <stdio.h>
3 int main (void ) {
/* Calling function of integer type return.*/
5 printf("Calling function myFunc()n");
printf("Returned value is %c", myFunc ());
7 return 0;
}
9
/* Declaring function of integer type return.*/
11 int myFunc () {
return ’A’;
13 }
✌
✆
170 Basic C
✞
Calling function myFunc ()
Returned value is A
✌
✆
Compiler does not care about parameters of the declared function prototype. The com-
piler will not be able to perform compile-time checking of argument types. The validity
of arguments is checked during the program run time and sometime program returns
garbage value.
✞
#include <stdio.h>
2
int main (void ) {
4 /* Calling function of integer type return.*/
printf("Calling function myFunc()n");
6 printf("Returned value is %c", myFunc (65) );
return 0;
8 }
10 /* Declaring function of integer type return.*/
int myFunc(int i, int j) {
12 return i + j;
}
✌
✆
1.9.3 Function Types
In old C standards, each function was considered as integer type, while in new implemen-
tation of C standards, the type of the function may be integer, float, double, character
or void. Declaration of a function type is based on the return value of the function not
on the argument type. See example below:
✞
1 #include <stdio.h>
/* Integer type function .*/
3 int max(int a, int b) {
if (a > b)
5 return a;
else
7 return b;
}
9
int main (int argc , char *argv [ ]) {
11 /* integer specifier required to *
*print return value from function .*/
13 printf("Max of %d and %d is %dn", 2, 3, max(2, 3));
return 0;
15 }
✌
✆
✞
Max of 2 and 3 is 3
✌
✆
1.9. FUNCTION 171
In function ‘max’, two arguments are taken as inputs as integer and between them, greater
is returned as integer. Hence, here the function is declare as integer type. If the same
function is declared as float type then return value is a float value not integer value.
✞
1 #include <stdio.h>
/* Float type function .*/
3 float max(int a, int b) {
if (a > b)
5 return a;
else
7 return b;
}
9
int main (int argc , char *argv [ ]) {
11 /* Float specifier required to print*
*return value from function . */
13 printf("Max of %d and %d is %fn", 2, 3, max(2, 3));
return 0;
15 }
✌
✆
✞
Max of 2 and 3 is 3.0000
✌
✆
In case of void functions, the function should return with NULL value even if return
keyword is used inside the function. This type of function do something according to its
expression and stores the result in global variable.
✞
1 #include <stdio.h>
int f;
3
void sum(int a, int b) {
5 f = a+b;
/* Use of return keyword without any value.*/
7 return;
}
9
int main (int argc , char *argv [ ]) {
11 sum(2, 3);
printf("Sum of %d and %d is %dn", 2, 3, f);
13 return 0;
}
✌
✆
✞
Sum of 2 and 3 is 5
✌
✆
Use of return keyword in following manner are valid in void type functions.
✞
1 return; /* Legal return*/
return ""; /* Legal return */
3 return NULL ; /* Legal return */
return "; /* Illegal , " is null character code */
✌
✆
172 Basic C
return keyword is somewhat like exit keyword. After return keyword, anything inside
an expression block is skipped during program execution. Function returns the assigned
value and exits.
✞
#include <stdio.h>
2
int ret();
4
int main (void ) {
6 ret();
return 0;
8 }
10 int ret() {
int i = 0;
12 int loops = 15;
printf("Loop count is %dn", loops);
14 while (i < loops) {
printf("i is %dn", i);
16 if (i == 7) {
printf("Returning from the function at i=%dn", i);
18 printf("reaching before the loop value %dn", loops);
return 0;
20 }
i++;
22 }
return 0;
24 }
✌
✆
✞
Loop count is 15
i is 0
i is 1
i is 2
i is 3
i is 4
i is 5
i is 6
i is 7
Returning from the function at i=7
reaching before the loop value 15
✌
✆
A function with void return type can not be called through printf. For example
✞
1 #include <stdio.h>
#include <stdlib.h>
3
/* function return type is void */
5 void myF() {
printf("myF");
7 }
1.9. FUNCTION 173
9 int main () {
int i = 5, j = 3;
11 /* invalid use of void type function */
printf("%s", myF());
13
return 0;
15 }
✌
✆
program failed to compile and returns compile time error “invalid use of void”.
Never Reach Condition A function with return keyword, returns either NULL or some
alpha-numeric value after successful execution. Execution of function-script is terminated
after first successful return. If a function is designed in such manner that it has to reached
to only fixed return keywords then other return keywords if used are never reached by
the compiler. See the example given below:
✞
1 #include <stdio.h>
3 int executeMe (int i) {
if (i <= 10) { /* If i is less than or equal to 10 */
5 return 0;
} else { /* Otherwise */
7 return 1;
}
9 return -1; /* Mever reached */
}
11
int main () {
13 printf("%dn", executeMe (10) );
printf("%dn", executeMe (15) );
15 printf("%dn", executeMe (1));
return 0;
17 }
✌
✆
✞
0
1
0
✌
✆
1.9.4 Function Recursion
In C, a function can be called recursively, i.e. in nested form from within its body, without
using loop functions, i.e. for, while or do-while etc. See the example given below:
✞
1 #include <stdio.h>
int recFunc (int i, int j);
3
int recFunc (int i, int j) {
5 if (i == 0) {
return (2 + j);
174 Basic C
7 } else {
return recFunc(i - 1, j + 1);
9 }
}
11
int main (int argc , char ** argv ) {
13 int k = recFunc (4, 6);
printf("%d", k);
15 return 0;
}
✌
✆
✞
12
✌
✆
In above example, function ‘recFunc’ takes two arguments and checks the conditions for
its first argument. If it is true then it returns the sum of ‘2’ and second argument and
exits. Otherwise it returns the function ‘recFunc’ with new values of its two arguments.
As function calls itself, hence a loop like recursion is observed. There should be a condition
to be met and break the function recursion otherwise there shall be no return value. See
the following examples,
✞
1 #include <stdio.h>
int recFunc (int i, int j);
3
/* This type of recursion is not acceptable .*/
5 int recFunc (int i, int j) {
/*No Condition , No return value.*/
7 return recFunc(i - 1, j + 1);
}
9
int main (int argc , char ** argv ) {
11 int k = recFunc (4, 6);
printf("%d", k);
13 return 0;
}
✌
✆
If condition in the recursive function is not met then there is no return value from the
function. In the following example, if condition is never met therefore, there shall be no
return value from the recursive function.
✞
#include <stdio.h>
2 int recFunc (int i, int j);
4 int recFunc (int i, int j) {
/* Condition never met. No returned value.*/
6 if (i == 0) {
return (2 + j);
8 } else {
return recFunc(i, j + 1);
10 }
}
1.9. FUNCTION 175
12
int main (int argc , char ** argv ) {
14 int k = recFunc (1, 6);
printf("%d", k);
16 return 0;
}
✌
✆
There shall be no output on running of above two program.
1.9.5 Function As Argument
A function can pass to another function as its argument. The synopsis of the passing of
a function as argument to the other function tFunc() is given below:
✞
1 void tFunc(<data type > (*< func pointer >)());
✌
✆
See the example :
✞
1 #include <stdio.h>
#include <math .h>
3
/* Here *fp is pointer of the function sqrt */
5 void tFunc(char *name , double (*fp)()) {
int n;
7 printf("Testing function %s:n", name );
printf("%s: %10sn", "n", "Square Root ");
9 printf(" --------------n");
for (n = 0; n < 10; n++) {
11 printf("%d: %11.6fn", n, (*fp)(( double) n));
}
13 }
15 int main () {
tFunc("square root ", sqrt );
17 return 0;
}
✌
✆
✞
Testing function square root :
n: Square Root
--------------
0: 0.000000
1: 1.000000
2: 1.414214
3: 1.732051
4: 2.000000
5: 2.236068
6: 2.449490
7: 2.645751
8: 2.828427
9: 3.000000
✌
✆
176 Basic C
1.9.6 Function Callback
A callback is a piece of executable code that is passed as an argument to other code,
which is expected to call back (execute) the argument at some convenient time. In C,
there is no “callback” yet they are implemented by using function pointers. Following
example shows the possible call back.
✞
1 #include <stdio.h>
3 /* This function is calledback from other function .*/
int DoubleIt (int a) {
5 return 2 * a;
}
7
/* Pass DoubleIt function as argument named fPar .*
9 *The argument should be as function prototype . */
int myFunc(int (* fPar )(int)) {
11 int i = 10;
fPar (i);
13 }
15 int main () {
/* Pass function DoubleIt to myFunc */
17 printf("Result is : %dn", myFunc(DoubleIt ));
return 0;
19 }
✌
✆
✞
Result is : 20
✌
✆
The same above example is given in pointer format.
✞
1 #include <stdio.h>
3 /* This function is calledback from other function .*/
int *DoubleIt (int a) {
5 int *i;
i = (2 * a);
7 }
9 /* Pass DoubleIt function as argument named fPar .*
*The argument should be as function prototype . */
11 int *myFunc(int (* fPar )(int )) {
int i = 10;
13 (* fPar )(i);
}
15
int main () {
17 /* Pass function DoubleIt to myFunc */
printf("Result is : %dn", myFunc(DoubleIt ));
19 return 0;
}
✌
✆
1.9. FUNCTION 177
✞
Result is : 20
✌
✆
A function may be called from its pointer index if function pointer is saved in function
symbol table. See the example given below:
✞
1 #include <stdio.h>
#include <stdlib.h>
3 #include <dlfcn.h>
5 /* Memory allocation for 5 Function Pointers */
int (*FP [5]) ();
7
main (int argc , char **argv ) {
9 int i = 0;
void * myLib;
11
/* Function pointer */
13 void *fptr ;
15 /* Load function library */
myLib = dlopen("libtestdll .dll", RTLD_LAZY );
17
/* Find the function object of function "bar"*/
19 fptr = dlsym(myLib , "bar");
21 /* Assign address of library function "bar"*
*to all indexed function pointers (FP) */
23 for (i = 0; i < 5; i++) {
FP[i] = fptr ;
25 }
27 /* Call function from second FP address */
FP [1]();
29
/* Close Library */
31 dlclose (myLib);
33 return 0;
}
✌
✆
✞
called bar function from dll.
✌
✆
1.9.7 Memory Function
Memory functions in C, deals with memory. These functions are used to store, copy and
move data from one memory location to other memory location.
178 Basic C
mmap
To read or write to same file by two or more processes, mmap() function is used. Before
mapping a file to memory, file descriptor is obtained by using open() function as given
below:
✞
1 int fd;
fd=open ("<file name >", "<mode >");
✌
✆
The open function returns the file descriptor as integer value. ‘-1’ if it failed to open the
file otherwise a positive integer as file handle. Now, mmap() is called to map the file as
✞
data = mmap (<address >, <size >, <prot >, <flags >, <file id >,
<offset >);
✌
✆
‘address’ is the memory address where we want to mapped a file. By default its value is
‘0’ for automatic selection of address by the OS. ‘size’ is length of data of the file to be
mapped. ‘prot’ is a kind of access/permission to the file. Its values are PROT READ
for read only permission, PROT WRITE for write only permission and PROT EXEC for
execute permissions. ‘flags’ controls the sharing of changes or just keep them private.
The flag values are MAP SHARED or MAP PRIVATE for sharing and private mode
respectively. ‘offset’ is initial position of the file from where mapping of file data to
memory started. This value must be a multiple of the virtual memory page size. To get
the page size, getpagesize() function is used. See the example below:
✞
1 #include <stdio.h>
#include <stdlib.h>
3 #include <sys/mman .h>
#include <fcntl.h>
5
int main (int argc , char *argv []) {
7 int fd;
char *data ;
9 /* Read only mode of file .*/
if ((fd = open ("a.txt", O_RDONLY )) == -1) {
11 printf("Unable to open file ");
return 1;
13 }
/* Map file in memory with read only permissions */
15 data = mmap (0, 1024, PROT_READ , MAP_SHARED , fd , 0);
if (* data == -1) {
17 printf("Unable to map file ");
return 1;
19 }
printf("Byte at offset %d is ’%c ’n", 0, data [0]) ;
21 return 0;
}
✌
✆
✞
Byte at offset 0 is ’s’
✌
✆
1.9. FUNCTION 179
Each file which is mapped must be freed by using munmap function as
✞
1 int munmap(<address >, <size >);
✌
✆
Once the file is unmapped, data access with old file descriptor is not possible and will
return segmentation fault error. If multiple protected access permissions are granted by
using OR (|) operator in mmap() function, then the file access mode should be according
the access granted. See the example below in which protected access mode is grated for
read and write. Therefore, the file access mode in open() function is “rw” type (i.e. read
and write type via O RDWR).
✞
1 #include <stdio.h>
#include <stdlib.h>
3 #include <sys/mman .h>
#include <fcntl.h>
5
int main (int argc , char *argv []) {
7 int fd;
char *data ;
9 /* Read and write mode of file .*/
if ((fd = open ("a.txt", O_RDWR)) == -1) {
11 printf("Unable to open file ");
return 1;
13 }
/* Map file in memory with read & write permissions */
15 data = mmap (0, 1024, PROT_READ |PROT_WRITE , MAP_SHARED , fd , 0);
if (* data == -1) {
17 printf("Unable to map file ");
return 1;
19 }
printf("Byte at offset %d is ’%c ’n", 0, data [0]) ;
21 data [10] = ’1’;
printf("Byte at offset %d is ’%c ’n", 10, data [10]);
23 return 0;
}
✌
✆
✞
Byte at offset 0 is ’a’
Byte at offset 10 is ’1’
✌
✆
File Mode Key Numeric Description
O RDONLY 0 Read only access to file.
O WRONLY 1 Write only access to file.
O RDWR 2 Read and write access to file.
Table 1.21: File access mode.
180 Basic C
A segment of file may be mapped by using mmap function with setting file pointer by
lseek function as given below:
✞
....
2 for (j = 0; j <= bk; j++) {
/* Map file for block size ‘bks’ from ‘offset’*/
4 data = mmap (0, bks , PROT_READ | PROT_WRITE , 
MAP_SHARED , fd , offset);
6 /* Chagne file pionter ‘fd’ to next block */
int offset=lseek(fd , bks , SEEK_CUR );
8 }
....
✌
✆
File Access Modes
The protection and permission codes of a file in Linux OS system are given in the following
table.
Mode Permission Value Protection Value
NONE 0 0
READ 4 1
WRITE 2 2
EXEC 1 4
Permission to a file in Linux OS system for a user, group or system is managed by
chmod command. This command accepts the file protection mode in numeric form as
given below:
✞
1 chmod 777 <file or dir >
✌
✆
In Linux OS system, a file has three levels of discretionary protection and permission.
permission to a file in Linux OS system is represented by a string that looks like “Zrwxr-
wxrwx”, in which first character, ‘Z’ defined type of directory or file, i.e. ‘d’ for directory,
‘l’ for linked file, ‘s’ for setuid bit, ‘t’ for the sticky bit etc. Next three characters (triads)
are protection/permission mode for owner, second is for group and third is for all other
users. Character ‘r’, ‘w’ and ‘x’ represents to read, write and execute modes respectively.
If user has readonly permission to a file then three characters shall be looked like ‘r –
–’ where dashes represent no write and no execute permissions to the user for the given
file or directory. The permission code in chmod command, as given above is splited in
all possible combinations before defining user’s permission and execution of chmod com-
mand. Note that, in permission code ‘777’, first ‘7’ is for owner second ‘7’ is for group
and third ‘7’ is for all other users. For example, ‘7’ is splitted in 4+2+1 form to mark
a file as read-write-exec. ‘3’ as 0+2+1, i.e. read-write- –. ‘5’ as 4+0+1, i.e. read- – -
exec. Permission with ‘–’ means files can not be either read, write or permissioned and
directories can not be permissioned with cd command. If there is no valid combinations
1.9. FUNCTION 181
are made from permission code, then invalid mode error is thrown by the system. The
permission string can be equivalently computed with binary values as shown below:
✞
1 -rwxrwxrwx ; permission string
111111111 ; Binary values
✌
✆
The triad values for owner (let) are computed for read permission as 1002 = 410, for write
permission as 0102 = 210, for read-write 1102 = 610 and so on.
memset
Syntax of memset() function is
✞
void *memset(void *s, int c, size_t n);
✌
✆
The memset() function converts ‘c’ into unsigned char, then stores the character into the
first ‘n’ bytes of memory pointed-by ‘s’. A simple example is
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 /* iniitalized a string */
char str1 [ ] = "These is memset !!!! ";
7 /* memset first six characters of the string*/
memset(str1 , ’-’, 6);
9 puts (str1 );
/* iniitalized a string */
11 char str2 [ ] = "These is memset !!!! ";
/* memset first three characters of the string*/
13 memset(str2 , ’-’, 3);
puts (str2 );
15 /* iniitalized a string */
char str3 [ ] = "These is memset !!!! ";
17 /* memset first four characters of the string*/
memset(str3 , ’-’, 4);
19 puts (str3 );
return 0;
21 }
✌
✆
✞
------is memset !!!!
---se is memset !!!!
----e is memset !!!!
✌
✆
memcpy
The memcpy() function shall copy n bytes from the object pointed to by ‘source’ into the
object pointed to by ‘destination’. If copying takes place between objects that overlap,
the behavior is undefined. The function returns ‘destination’. Syntax of the function is
182 Basic C
✞
1 void *memcpy(void * restrict <destination >, 
const void * restrict <source >, size_t <n>);
✌
✆
Because the function does not have to worry about overlap, it can do the simplest copy
it can.
✞
#include <stdio.h>
2 #include <string.h>
4 int main () {
const char src [50] = "Experimental string.";
6 char dest [50];
8 printf("Before memcpy destination is : %sn", dest );
memcpy(dest , src , strlen(src) + 1);
10 printf("After memcpy destination is : %sn", dest );
12 return (0);
}
✌
✆
✞
Before memcpy destination is :
After memcpy destination is : Experimental string.
✌
✆
memcpy() function is very useful when a user defined function pointer is required to
return the local pointer defined inside the function.
✞
#include <stdio.h>
2
char *toLower (char str[ ]) {
4 /* Initiate local string pointer */
char *s = NULL ;
6 /* Allocate memory for local pointer */
s = malloc(sizeof (char )*(1024));
8 int i = 0;
/* Create a local array for storing *
10 * modified string received from *
* from function argument . */
12 char st [1024];
while (str[i] != ’0 ’) {
14 /* Capital letters starts from *
* char code 65 to 90. While *
16 * small letters starts from 97*
* to 122. A difference of +32 */
18 if (str[i] >= 65 && str[i] <= 90) {
st[i] = str[i] + 32;
20 } else {
st[i] = str[i];
22 }
i++;
24 }
1.9. FUNCTION 183
st[i] = ’0’;
26 /* Copy array into memory as a pointer . */
memcpy(s, st , 1024);
28 /* Return function pointer.*/
return s;
30 /* Free allocated memory.*/
free (s);
32 }
34 int main (void ) {
char str[ ] = "This iS MY striNg.";
36 printf("Actual string is :");
printf(""%s"n",str);
38 printf("Lower case string is :");
printf(""%s"", toLower (str));
40 return 0;
}
✌
✆
✞
Actual string is : "This iS MY striNg ."
Lower case string is : "this is my string ."
✌
✆
memmov
The memmove() function shall copy n bytes from the object pointed to by ‘source’ into
the object pointed to by ‘dest’. Copying takes place as if the n bytes from the object
pointed to by ‘source’ are first copied into a temporary array of n bytes that does not
overlap the objects pointed to by ‘dest’ and ‘source’, and then the n bytes from the
temporary array are copied into the object pointed to by ‘dest’. The function returns the
value of ‘dest’. The easy way to implement this without using a temporary array is to
check for a condition that would prevent an ascending copy, and if found, do a descending
copy. Unlike the memcpy(), this function guaranteed to move contents from source to
destination even if the memory regions pointed by ‘source’ and ‘dest’ overlaps. Its syntax
is
✞
void *memmove (void * <dest >, const void *<source >, size_t <n>);
✌
✆
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 char str[ ] = "Experimental string";
memmove (str + 10, str + 5, 5);
7 puts (str);
return 0;
9 }
✌
✆
✞
Experimentimentring
✌
✆
184 Basic C
memchr
The memchr() function shall locate the first occurrence of ‘c’ (converted to an unsigned
char) in the initial n bytes (each interpreted as unsigned char) of the object pointed to
by ‘string’. If ‘c’ is not found, memchr() returns a null pointer. Its syntax is
✞
1 void *memchr(const void *<string >, int <c>, size_t <n>);
✌
✆
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 char * pch;
char str[ ] = "Example string";
7 pch = (char *) memchr(str , ’e’, strlen(str));
if (pch != NULL )
9 printf("’e’ found at position %d.n", pch - str + 1);
else
11 printf("’e’ not found.n");
return 0;
13 }
✌
✆
✞
’e’ found at position 7.
✌
✆
memcmp
The memcmp() function shall compare the first n bytes (each interpreted as unsigned
char) of the object pointed to by ‘mem1’ to the first n bytes of the object pointed to
by ‘mem2’. The sign of a non-zero return value shall be determined by the sign of the
difference between the values of the first pair of bytes (both interpreted as type unsigned
char) that differ in the objects being compared.
✞
1 int memcmp(const void *<mem1 >, const void *<mem2 >, size_t <n>);
✌
✆
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 char buff [ ] = "Artificial ";
char buff2[ ] = "ARtificial ";
7
int n;
9
n = memcmp(buff , buff2 , sizeof (buff ));
11
if (n > 0)
13 printf(" ’%s’ is greater than ’%s ’.n", buff , buff2);
else if (n < 0)
15 printf(" ’%s’ is less than ’%s ’.n", buff , buff2);
1.9. FUNCTION 185
else
17 printf(" ’%s’ is the same as ’%s ’.n", buff , buff2);
19 return 0;
}
✌
✆
✞
’Artificial ’ is greater than ’ARtificial ’.
✌
✆
1.9.8 Unicode Support
C provides unicode support for the native operating systems which have their own unicode
support. To set the native local language
✞
1 char *locale = setlocale (LC_CTYPE , " en_IN.UTF -8");
✌
✆
The function setlocale() is defined in the macro “locale.h”. If native locale doesn’t use
UTF-8 encoding it need to replace the empty string with a locale like “en IN.UTF-8”.
Localisation environment has following parameters
✞
1 ANG=en_US
LC_CTYPE ="en_US"
3 LC_NUMERIC ="en_US"
LC_TIME=" en_US"
5 LC_COLLATE ="en_US"
LC_MONETARY ="en_US"
7 LC_MESSAGES ="en_US"
LC_PAPER ="en_US"
9 LC_NAME=" en_US"
LC_ADDRESS ="en_US"
11 LC_TELEPHONE ="en_US"
LC_MEASUREMENT ="en_US"
13 LC_IDENTIFICATION ="en_US"
LC_ALL=
✌
✆
User can change any specific environmental parameter by using method given above or
setting all environment to locals by setting ‘LC ALL’ as shown below.
✞
char *locale = setlocale (LC_ALL , "en_IN.UTF -8");
✌
✆
An example is
✞
1 #include <stdio.h>
#include <wchar.h>
3 #include <stdlib.h>
#include <locale.h>
5
int main (void ) {
7 /* If your native locale doesn’t use UTF -8 encoding *
* you need to replace the empty string with a *
186 Basic C
9 * locale like "en_US.utf8 " */
char * locale = setlocale (LC_CTYPE , "en_IN.UTF -8");
11 FILE *in = fopen("a.txt", "r");
13 wint_t c;
while ((c = fgetwc(in)) != WEOF )
15 putwchar (c);
fclose(in);
17
return EXIT_SUCCESS ;
19 }
✌
✆
1.10 Procedures & Functions
A function is often executed (called) several times, called from different locations, during
a single execution of the program. After finishing a subroutine, the program will branch
back (return) to the point after the call. A function is like a black box. It takes inputs,
does something with them, then spits out an answer.
✞
1 #include <stdio.h>
3 void P_Loop(void ) {
int i;
5 for (i = 1; i <= 5; i++) {
printf("%d ", i * i);
7 }
}
9
int main (void ) {
11 P_Loop ();
printf("n");
13 P_Loop ();
return 0;
15 }
✌
✆
The output is
✞
1 4 9 16 25
1 4 9 16 25
✌
✆
1.10.1 Code Optimisation
It is very common that in a program, there are excess lines of script or it has time/memory
consuming algorithm. Ultimately program takes longer time for execution. By using ad-
vance methods of algorithm and script writing we can reduce the size as well as execution
time of the program. It is known as code optimization. In other words, code optimization
is a method of code modification to improve code quality and efficiency. A program may
1.10. PROCEDURES & FUNCTIONS 187
be optimized so that it becomes a smaller size, consumes less memory, executes more
rapidly or performs fewer input/output operations.
Illustrated Example Assume that we have to find all the prime numbers within 1 to
20. We write a program in which each number is divided by all numbers less than to it.
For example, to check whether 19 is a prime or not, it is divided by integers started from
2 to 19 and if any of the divisor returns the zero as remainder then the number 19 is not
prime.
✞
#include <stdio.h>
2 #include <stdlib.h>
4 int main () {
int n, i = 1, j, m = 0;
6 printf("Enter Limit of Prime Number : ");
scanf("%d", &n);
8 while (i <= n) {
int k = 0;
10 for (j = 2; j < i; j++) {
if (i % j == 0) {// line to be optimised
12 k++;
}
14 }
if (k == 0) {
16 m++;
printf("%d is a prime number .n", i);
18 }
i++;
20 }
printf("Total %d primes are found.n", m);
22 return 0;
}
✌
✆
Another concept is that, if a number, ‘n’, is not divisible by a maximum integer value of
‘n/2’ then it is not divisible by any integers larger ‘n/2’. For example if 19 is not divisible
by maximum integer value of 19/2, ie 9 then 19 never be completely divisible by 10 or
more. By this method we reduce the iteration loops in the program. Above example can
be rewritten as
✞
1 #include <stdio.h>
#include <stdlib.h>
3
int main () {
5 int n, i = 1, j, m = 0;
printf("Enter Limit of Prime Number : ");
7 scanf("%d", &n);
while (i <= n) {
9 int k = 0;
for (j = 2; j <= i/2; j++) {// line is optimised
11 if (i % j == 0) {
k++;
188 Basic C
13 }
}
15 if (k == 0) {
m++;
17 printf("%d is a prime number .n", i);
}
19 i++;
}
21 printf("Total %d primes are found.n", m);
return 0;
23 }
✌
✆
By this way we have reduce the execution time of the program (better performance)
without compromising its output. Again if a number ‘n’ is divisible by ‘2’, above program
checks the divisibility upto maximum integer value of ‘n/2’ by several iteration even if it
was confirm that the number ‘n’ is not prime in first iteration. To enhance the performance
of the program, we can again optimize the code by using break-continue function when
number is checked and confirmed that it is not prime in first iteration.
✞
1 #include <stdio.h>
#include <stdlib.h>
3
int main () {
5 int n, i = 1, j, m = 0;
printf("Enter Limit of Prime Number : ");
7 scanf("%d", &n);
while (i <= n) {
9 int k = 0;
for (j = 2; j <= i / 2; j++) {
11 if (i % j == 0) {
k++;
13 break;/* no further check that the number*
*is primeif it is declared not a *
15 *prime in first few iterations . */
}else {
17 continue ;
}
19 }
if (k == 0) {
21 m++;
printf("%d is a prime number .n", i);
23 }
i++;
25 }
printf("Total %d primes are found.n", m);
27 return 0;
}
✌
✆
It again enhance the performance of program by multiple times. Similarly, if given number
is even number then it shall never be prime and if given number is odd number then it
shall not be prime if it has a perfect square-root. Again, square-root of odd number is
1.10. PROCEDURES & FUNCTIONS 189
only odd number. It means we have to check the divisibility of given number by all odd
numbers less than or equal to square root of the given number. By this way we can
further optimize the code for prime numbers.
✞
#include <math .h>
2 #include <stdio.h>
4 int main () {
int n = 147853;
6 int x, y = 1;
int sq = sqrt (n) + 1;
8 if (n < 2)
y = 0;
10 if (n == 2 || n == 3)
y = 1;
12 if (n % 2 == 0)
y = 0;
14 for (x = 3; x <= sq; x += 2) {
if (n % x == 0)
16 y = 0;
}
18 if (y == 1) {
printf("A primen");
20 } else {
printf("Not A primen");
22 }
return 1;
24 }
✌
✆
Execution Time In good programming practices, codes are written in such manner
that they took least execution time with optimum performance. Using clock() function,
we can get the execution time of the program. A simple example is given below.
✞
#include <stdio.h>
2 #include <stdlib.h>
#include <time .h>
4
int main () {
6 clock_t startTime = clock();
int n = 1000000 , i = 1;
8 while (i <= n) {
i++;
10 }
clock_t endTime = clock();
12 double td = (endTime - startTime ) / (double) CLOCKS_PER_SEC ;
printf("Program has run for %5.8 f secondsn", td);
14 return 0;
}
✌
✆
✞
Program has run for 0.00000200 seconds
✌
✆
190 Basic C
Additional to this, some time it is required to know the local time (computer clock time)
for best performance of the program. Here is an example that uses time.h header file to
get the local time. The code line
✞
1 time_t time (time_t *seconds );
✌
✆
returns the time lapsed since the mid night of January 1, 1970, measured in seconds. If
‘seconds’ is not NULL, the return value is also stored in variable ‘seconds’.
✞
1 #include <stdio.h>
#include <time .h>
3
int main () {
5 time_t seconds;
7 seconds = time (NULL );
printf("Hours since January 1, 1970 = %ldn", seconds / 3600);
9
return (0);
11 }
✌
✆
✞
Hours since January 1, 1970 = 405089
✌
✆
Another example is
✞
1 #include <time .h>
#include <stdlib.h>
3 #include <stdio.h>
5 int main (void ) {
time_t current_time ;
7 char * c_time_string ;
int i = 5;
9 while (i > 0) {
sleep (1);
11 /* Obtain current time . */
current_time = time (NULL );
13 /* Convert to local time format. */
c_time_string = ctime(& current_time );
15 printf("Current time is %d, %s", current_time ,
c_time_string );
i--;
17 }
return EXIT_SUCCESS ;
19 }
✌
✆
✞
Current time is 1458321446 , Fri Mar 18 22:47:26 2016
Current time is 1458321447 , Fri Mar 18 22:47:27 2016
Current time is 1458321448 , Fri Mar 18 22:47:28 2016
Current time is 1458321449 , Fri Mar 18 22:47:29 2016
1.10. PROCEDURES & FUNCTIONS 191
Current time is 1458321450 , Fri Mar 18 22:47:30 2016
✌
✆
Specifier Output Format
%a Short weekday name
%A Full weekday name
%b Short month name
%B Full month name
%c Time stamp
%d Day of the month
%H Hour in 24h format
%I Hour in 12h format
%j Day of the year
%m Month as a decimal number
%M Minutes
%p AM or PM
%S Seconds
%U Week number, first day of first week is Sunday
%w Weekday as a decimal number with Sunday as 0 (0-6)
%W Week number, first day of first week is Monday
%x Date representation
%X Time representation
%y Two digit Year format (00-99)
%Y Four digit Year format
%Z Timezone name
%% A % sign
Table 1.22: Date & time format specifiers.
1.10.2 Increments & Decrements
The character set ‘++’ is used to increase the value by one and −− is used to decrease
the value by one of the variable with which the character set is prefixed or post-fixed.
There are two ways to use these notations. One is ‘++n’ and other is ‘n++’. Both have
same meaning but first is used where value is to be used after one increment while later
is used where value is to be increase by one after using it.
192 Basic C
✞
1 #include <stdio.h>
#include <stdlib.h>
3
int main (void ) {
5 int i = 0;
printf("use of ++i n");
7 while (i < 3) {
/* calling & placing at same place.*/
9 printf("%d => %d n", i, ++i);
}
11 printf("use of i++ n");
int j = 0;
13 while (j < 3) {
printf("%d => %d n", j, j++);
15 }
return EXIT_SUCCESS ;
17 }
✌
✆
✞
use of ++i
1 => 1
2 => 2
3 => 3
use of i++
1 => 0
2 => 1
3 => 2
✌
✆
If increment or decrements is used inside a loop, there are no difference in the use of ‘i++’
or ‘++i’.
✞
#include <stdio.h>
2 #include <stdlib.h>
4 int main (void ) {
int i = 0;
6 printf("Use of i++ in while loop n");
while (i < 3) {
8 /* first increment .*/
i++;
10 /* then use.*/
printf(":-> %dn", i);
12
}
14 printf("Use of ++i in while loop n");
int j = 0;
16 while (j < 3) {
/* first increment .*/
18 ++j;
/* then use.*/
20 printf(":-> %dn", j);
1.10. PROCEDURES & FUNCTIONS 193
22 }
return EXIT_SUCCESS ;
24 }
✌
✆
✞
Use of i++ in while loop
:-> 1
:-> 2
:-> 3
Use of ++i in while loop
:-> 1
:-> 2
:-> 3
✌
✆
This increment operator can not be used in variable initialization or with constants like
3 + + or directly in output stream functions like printf. The following type of syntax are
illegal.
✞
int i=2++; // illegal coding
2 printf("Increment of 2 is %dn" ,2++);// illegal coding
✌
✆
The same methods can be used for decrements operator. In increments or decrements
operations, value of variable i is incremented by one and then the result is assigned to
variable i. This is why, constant values can not be used with this unary operator, i.e.
5 + + and + + 5 cause compile time errors. See another example for i + + and + + j
unary operators.
✞
#include <stdio.h>
2
int main (int argc , char ** argv ) {
4 int i = 0;
while (i < 3) {
6 printf("i is %dn", i++);/* started from 0*/
}
8 printf("n");
int j = 0;
10 while (j < 3) {
printf("j is %dn", ++j);/* started from 1*/
12 }
return 0;
14 }
✌
✆
✞
i is 0
i is 1
i is 2
j is 1
j is 2
j is 3
✌
✆
194 Basic C
Again, before summing up this section, always remember that k + 1 and k + + results
increment of variable ‘k’ by one. But first expression is purely different to second ex-
pression. In first expression, the value of ‘k’ remains unchanged only results reflects to
increment by one, while in second expression, value of ‘k’ is incremented by one and again
assigned to it.
✞
1 #include <stdio.h>
3 int main (int argc , char ** argv ) {
int k = 0, l = 0;
5 printf("k+1 is %d and l++ is %dn", k+1, l++);
printf("k+1 is %d and l++ is %dn", k+1, l++);
7 printf("k+1 is %d and l++ is %dn", k+1, l++);
return 0;
9 }
✌
✆
✞
k+1 is 1 and l++ is 0
k+1 is 1 and l++ is 1
k+1 is 1 and l++ is 2
✌
✆
When increment and decrements operators are used simultaneously, then increment and
decrements is performed simultaneous in order.
✞
1 #include <stdio.h>
#include <stdlib.h>
3
int myF(int i) {
5 int j = 1, re , r = 2;
while (j < i) {
7 re = (r++) *(++ r);//re = (2) * (4); r = 4;
j++;
9 }
return re;
11 }
13 int main () {
int i = 5, j = 3;
15 printf("%d", myF (5));
17 return 0;
}
✌
✆
✞
80
✌
✆
In above program, in each loop, first value of r in r++ is used and then it is incremented.
The value of r in ++r is incremented and then used. Therefore, in first loop, the equivalent
expression shall be
✞
1 re = (2) * (4);
✌
✆
1.10. PROCEDURES & FUNCTIONS 195
And for next loop, the new value of r is 4. In case of increment operator is used with
array elements like
✞
1 a[i]=i++;
✌
✆
In this case, initial value of ‘i’ is taken and incremented by one. This original value
is stored as element of array ‘a’, at index position given by incremented ‘i’, i.e. ‘i+1’.
Actually, for any value of ‘i’ above expression becomes
✞
1 a[i+1]= i;
✌
✆
See the example below
✞
1 #include <stdio.h>
3 int main (int argc , char *argv []) {
int i = 80;
5 int j = i;
char a[100];
7 /*In following expression , first value of i*
*is used and then it is incremented . Value*
9 *of i stored at array element as a[i++]= i */
a[i] = i++;
11 /* Actual i and equivalent char */
printf("%d=>%cn", j, j);
13 /* Values stored in array as its*
*element for initial i values */
15 printf("a[%d]=%cn", j, a[j]);
/* Actual array element values*/
17 printf("a[%d]=%cn", i, a[i]);
return 0;
19 }
✌
✆
✞
80=>P
a[80]=(
a[81]=P
✌
✆
Again see the following example, in which we try to get the result 110 by multiplying
increment operators.
✞
1 #include <stdio.h>
3 int main (int argc , char *argv []) {
int i = 10;
5 printf("%dn", i++ * i++);
return 0;
7 }
✌
✆
✞
100
✌
✆
196 Basic C
But actual result is 100 rather than 110. It means after using the current value of ‘i’, ‘i’
does not goes increment for next use of ‘i’. It reason is that, C does not guaranteed to
increment the value of ‘i’ just after using it but it increments value of ‘i’ sometime before
the expression is considered “finished” or just before the next “sequence point”.
1.10.3 Static Function
In a program, if a function is declared as static then it can only be called from the same
file in which it is declared. It can not called from the other files. The syntax of static
function is
✞
1 static int compare(int a, int b) {
return (a + 4 < b) ? a : b;
3 }
✌
✆
An example of static function is
✞
1 #include <stdio.h>
3 static int compare(int a, int b) {
return (a > b) ? a : b;
5 }
7 int main () {
int j;
9 j = compare (2, 4);
printf(":-> %d.n", j);
11 return 0;
}
✌
✆
✞
:-> 4.
✌
✆
1.10.4 Function with Variable Arguments
A static function can be called by its prototype. Normally in static functions number
of arguments remain fix but variable number of arguments can also be passed to the
function. Calling of a function with variable arguments is given in following example.
✞
1 #include <stdlib.h>
3 #define MAXARGS 3
int var_arg ();
5
int main () {
7 var_arg (1, 2, 3);
return 0;
9 }
11 int var_arg (int a) {
1.10. PROCEDURES & FUNCTIONS 197
int i = 0;
13 while (i < MAXARGS) {
printf("%d argument is %d.n", i, (&a)[i]);
15 i++;
}
17 return a;
}
✌
✆
A ‘var arg’ function is defined in prototype as null variables
✞
int var_arg ();
✌
✆
This prototype function is defined as single argument list.
✞
1 int var_arg (int a)
✌
✆
When function is called with three integer arguments, this argument list is passed to the
function definition as a list.
✞
1 var_arg (1, 2, 3);
✌
✆
Following line in the program
✞
1 printf("%d argument is %d.n", i, (&a)[i]);
✌
✆
prints the each element of the variable list of ‘a’. Second method uses macros defined in
the header file <stdarg.h>.
✞
1 #include <stdio.h>
#include <stdarg.h>
3
void varStrings (const char *f, ...) {
5 int max_args = 5;
va_list args ;
7 va_start (args , max_args );
printf("%sn", f);
9 while (max_args --)
puts (va_arg(args , const char *));
11 va_end(args );
}
13
int main () {
15 varStrings ("f", "Mary ", "had", "a", "little", "lamb ");
return 0;
17 }
✌
✆
The syntax variable argument function requires at least one fixed argument before the
‘...’. Here ‘va list’ creates memory for the variable list ‘valist’. ‘va start’ function accepts
arguments and stores in the variable list ‘valist’ memory. ‘va arg’ function returns the
variable value from variable list ‘valist’. ‘va end’ function cleans the memory reserved
for valist. In pursuance to standard method of programming, in a function with variable
198 Basic C
arguments, first argument/element should be an integer, representing the number of ar-
guments to be passed to the function. In following example, sum of integers by passing
variable arguments is obtained.
✞
1 #include <stdarg.h>
3 int sum(int num , ...) {
va_list ap;
5 int total = 0;
va_start (ap , num);
7 while (num > 0) {
total += va_arg(ap , int);
9 num --;
}
11 va_end(ap);
return total;
13 }
15 int main () {
/* First argument determines the number of **
17 ** following arguments , those shall be used **
** in the sum function . Here it is 5. */
19 int a = sum(5, 1, 2, 3, 4, 6);
21 /* First argument determines the number of **
** following arguments , those shall be used **
23 ** in the sum function . Here it is 2. */
int b = sum(2, 3, 5, 8);
25 printf("Sums are %d and %dn", a, b);
return 0;
27 }
✌
✆
✞
Sums are 16 and 8 respectively .
✌
✆
1.10.5 Indirect Call of Function
In C, the input is considered as string even though input contains the name of inbuilt
functions or operators. For example, input “sin(90)” is considered as string which is a
group of ‘s’, ‘i’, ‘n’, ‘(’, ‘9’, ‘0’, ‘)’ and NULL characters rather than sine operator on
operand ‘90’. Using indirect call of a function, we can execute a function by supplying
function name as string input.
✞
1 #include <stdio.h>
#include <stdlib.h>
3 #include <math .h>
5 double Equ1 (double x) {
return x;
7 }
1.10. PROCEDURES & FUNCTIONS 199
9 double Equ2 (double x) {
return x * x;
11 }
13 double Equ3 (double x) {
return log(x);
15 }
17 typedef double (* Eqn)(double);
19 int main () {
int i;
21 double ic;
23 const char *EqnNames [3] = {
"Equ1 ", "Equ2 ", "Equ3 "
25 };
Eqn FEqu [ ] = {Equ1 , Equ2 , Equ3 };
27
for (i = 0; i < (sizeof (FEqu ) / sizeof (Eqn)); i++) {
29 ic = (* FEqu [i])(i + 1);
printf("Eqn Name = %5s : a=%d : Result=%lfn",
31 EqnNames [i], i + 1, ic);
}
33 return 0;
}
✌
✆
✞
Eqn Name = Equ1 : a=1 : Result =1.000000
Eqn Name = Equ2 : a=2 : Result =4.000000
Eqn Name = Equ3 : a=3 : Result =1.098612
✌
✆
1.10.6 Preprocessor Macros
Preprocessors are used to define macros or manifest constants and are included in the
header of source file. Preprocessors can be defined separately in a file having extensions
‘.h’ or in the same source file. Some of the useful pre-processors are explained below.
Literals
The token reserved for the preprocessor is the octothorp, #, and the preprocessor makes
three entirely different uses of it. Using, this token we can put the macros within the
function. Whitespace before the # is ignored. Next use of # in a macro makes input a
string, known as compound literal. See the example below:
✞
1 #include <stdio.h>
#define myMacro (v) printf (#v " : %dn", v);
3
int main () {
200 Basic C
5 myMacro (10 / 5);
myMacro (15 / 5);
7 return 0;
}
✌
✆
✞
10 / 5 : 2
15 / 5 : 3
✌
✆
Tokens
Body of a macro is considered as a string of tokens rather than a string of characters. C
preprocessor tokens are the separate “words” in the body of a macro definition. They are
separated from one another by white spaces. For example, the definition
✞
#define FOUR 2*2
✌
✆
has one token-the sequence 2*2, but the definition
✞
1 #define SIX 2 * 3
✌
✆
has three tokens 2, *, and 3. Character, strings and token strings differ from each other.
It depends on how how multiple spaces are treated in a macro body. The preprocessor
doesn’t make calculations; it just substitutes strings. For example
✞
1 #include <stdio.h>
3 #define SQUARE(X) X*X
5 int main (void ) {
int x = 4;
7 printf("x = %dn", x);
printf("SQUARE(x): %d", SQUARE(x));
9
/* Above statement is equivalent to *
11 * printf (" SQUARE(x): %d", x*x); */
return 0;
13 }
✌
✆
✞
x = 4
SQUARE(x): 16
✌
✆
In above example value of ‘x’ is passed to predefined function ‘SQUARE(X)’ and the
function replaces ‘X’ by ‘x’ as ‘x*x’ and ultimately ‘4*4’. Now the result is ‘16’. If the
‘x’ passed to the function as shown in the given example then
✞
#include <stdio.h>
2
#define SQUARE(X) X*X
1.10. PROCEDURES & FUNCTIONS 201
4
int main (void ) {
6 int x = 2;
printf("x = %dn", x);
8 printf("SQUARE(x): %d", SQUARE(x+2));
10 /* above statement is equivalent to *
* printf (" SQUARE(x): %d", x+2*x+2); */
12 return 0;
}
✌
✆
✞
x = 2
SQUARE(x): 8
✌
✆
Result is ‘8’ rather than predicted as ‘16’. The reason behind it is that when ‘x+2’ is
passed to the function ‘SQUARE’, it replaces ‘X*X’ by ‘x+2’ as ‘x+2*x+2’ and it gives
the ultimately result ‘2+2*2+2’ that is ‘8’. Again
✞
#include <stdio.h>
2
#define SQUARE(X) X*X
4
int main (void ) {
6 /* Initial declaration of x=2. */
int x = 2;
8
/* x=2 */
10 printf("x = %dn", x);
12 /* In below line , x in incremented *
* by 1and it becomes x=2+1=3 before*
14 * it passes to macro SQUARE(). */
printf("SQUARE(x): %d", SQUARE (++x));
16
/* Above statement is equivalent to *
18 * printf (" SQUARE(x): %d", ++x*++x);*
* Here again x is incremented by 1 *
20 * from its previous declaration *
* and it becomes x =3+1=4. */
22 return 0;
}
✌
✆
✞
x = 2
SQUARE(x): 16
✌
✆
#if, #else, #elif, #endif
These are also known as conditionals. The #if checks whether a controlling condition
expression evaluates to zero or nonzero, and excludes or includes a block of code respec-
202 Basic C
tively.
✞
#if 1
2 /* This block will be included */
#endif
4 #if 0
/* This block will not be included */
6 #endif
✌
✆
A simple example is
✞
#include <stdio.h>
2 /* Define row size 80*/
#define RSIZE 80
4 /*If row size is >200 set row size 200 */
#if RSIZE > 200
6 #undef RSIZE
#define RSIZE 200
8 /* else if row size is <50 set row size 50*/
#elif RSIZE <50
10 #undef RSIZE
#define RSIZE 50
12 /* Else set row size 100 :: it is true */
#else
14 #undef RSIZE
#define RSIZE 100
16 #endif
int main () {
18 printf("The row size is %d.n", RSIZE);
do_A ();
20 return 0;
}
22 /* Define row size 201*/
#define RSIZE_B 201
24 /*If row size is >200 set row size 200 :: It is true */
#if RSIZE_B > 200
26 #undef RSIZE_B
#define RSIZE_B 200
28 /* else if row size is <50 set row size 50*/
#elif RSIZE_B <50
30 #undef RSIZE_B
#define RSIZE_B 50
32 /* Else set row size 1001 */
#else
34 #undef RSIZE_B
#define RSIZE_B 100
36 #endif
38
do_A () {
40 printf("The row size is %d.n", RSIZE_B);
}
1.10. PROCEDURES & FUNCTIONS 203
✌
✆
✞
The row size is 100.
The row size is 200.
✌
✆
#ifdef & #ifndef
The #ifdef is similar to #if, except that the code block following it is selected if a macro
name is defined. In this respect,
✞
#ifdef NAME
✌
✆
is equivalent to
✞
1 #if defined NAME
✌
✆
A simple example is
✞
1 #include <stdio.h>
#ifndef __cplusplus
3 #error A C++ compiler is required !
#endif
5
int main () {
7 printf("C++ compiler needed !!!");
return 0;
9 }
✌
✆
The #ifndef is similar to #ifdef, except that the test is reversed:
✞
1 #ifndef NAME
✌
✆
is equivalent to
✞
1 #if !defined NAME
✌
✆
A simple example is
✞
1 #include <stdio.h>
#ifndef A
3 #define A 10
#endif
5
int main () {
7 printf(":-> %d.n", A); // printed "10"
return 0;
9 }
✌
✆
✞
:-> 10.
✌
✆
204 Basic C
#define
#define is used to define a preprocessor with known value. The syntax for this prepro-
cessor is
✞
1 #define <identifier > <token -string >
✌
✆
A program written in C is known as macro. When the computer reads the code, it
replaces all instances of a word with the specified expression. #define macro is used for
this purpose.
✞
1 #define PRICE_OF_PEN 5
✌
✆
When ever we want to print the price of pen, we use the word PRICE OF PEN instead of
the number 5, preprocessor will replace all instances of PRICE OF PEN with 5, which the
compiler will interpret as the literal integer 5. The preprocessor performs substitution,
that is, PRICE OF PEN is replaced by 5. Increments or decrements operation are not
allowed with preprocessor identifier. For example
✞
1 PRICE_OF_PEN ++ /* equals to 5++*/
/*OR*/
3 ++ PRICE_OF_PEN /* equals to ++5*/
✌
✆
are illegal and not allowed. Because above operation becomes
✞
1 5++
/*OR*/
3 ++5
✌
✆
and these are illegal in C. It means there is no need for a semicolon. The # and ##
operators are used with the #define macro. Using # causes the first argument after the
# to be returned as a string in quotes. For example, the function
✞
1 #define as_string ( s ) # s
✌
✆
will make the compiler turn this function
✞
1 puts ( as_string ( Hello World! ) ) ;
✌
✆
into
✞
1 puts ( "Hello World!" );
✌
✆
✞
1 #include <stdio.h>
#include <string.h>
3 #define as_string ( s ) # s
5 int main () {
puts ( as_string (Hello World !!!!));
7 return 0;
}
✌
✆
1.10. PROCEDURES & FUNCTIONS 205
✞
Hello World !!!!
✌
✆
Symbol ## concatenates what is before the ## with what is after it. After concate-
nation, strings becomes tokens. For example, in the following code snippets, function
‘concatenate’ converts two strings passed without double quotes, say x and y into token
xy.
✞
1 #define concatenate ( a, b ) a ## b
...
3 int xy = 10;
...
✌
✆
When this preprocessor is called from anywhere as shown in the below code line,
✞
printf( "%d", concatenate ( x, y ));
✌
✆
compiler turns this code line as
✞
1 printf( "%d", xy);
✌
✆
which will, of course, display 10 in the standard output.
✞
1 #include <stdio.h>
#include <string.h>
3 #define concatenate ( a, b ) a ## b
5 int main () {
int xy = 10;
7 printf("%d", concatenate (x, y));
return 0;
9 }
✌
✆
✞
10
✌
✆
It is possible to concatenate a macro argument with a constant prefix or suffix to obtain
a valid identifier as in
✞
1 #define make_function ( name ) int my_ ## name (int foo) {}
make_function ( bar )
✌
✆
which will define a function called my bar(). But it isn’t possible to integrate a macro
argument into a constant string using the concatenation macro. In order to obtain such an
effect, one can use the ANSI C property that two or more consecutive string constants are
considered equivalent to a single string constant when encountered. Using this property,
one can write
✞
#define eat( what ) puts ( "I’m eating " #what " today." )
2 eat( fruit )
✌
✆
206 Basic C
which the macro-processor will turn into
✞
puts ( "I’m eating " "fruit" " today." )
✌
✆
which in turn will be interpreted by the C parser as a single string constant. The following
trick can be used to turn a numeric constants into string literals
✞
1 #define num2str (x) str(x)
#define str(x) #x
3 #define CONST 23
puts (num2str (CONST));
✌
✆
This is a bit tricky, since it is expanded in 2 steps. First ‘num2str(CONST)’ is replaced
with str(23), which in turn is replaced with “23”.
✞
#include <stdio.h>
2 #include <string.h>
#define num2str (x) str(x)
4 #define str(x) #x
#define CONST 23
6
int main () {
8 puts ( num2str(CONST));
return 0;
10 }
✌
✆
✞
23
✌
✆
Using of catecanation symbol ‘##’ is useful when we have to create different user defined
functions with same signature of function which are being called through their pointer
addresses. See the example below, in which we have create a function by using ‘##’
symbol.
✞
1 #include <stdio.h>
3 #define init_fcn (name , type ) 
/* Create structure for object ‘age’*/
5 typedef struct 
{ 
7 type value; 
} F## name ; 
9 /* Create mf_age function */
inline F## name mf_## name (type v) 
11 { 
F## name t; 
13 t.value = v; 
return t; 
15 }
17 int main () {
init_fcn (age , int);
1.10. PROCEDURES & FUNCTIONS 207
19 init_fcn (Roll , int);
printf("%dn",mf_age (20) );
21 printf("%dn",mf_Roll (1020));
return 0;
23 }
✌
✆
✞
20
1020
✌
✆
A macro assigned with a numerical value using #define preprocessor can be assessed
from anywhere in the program. But it can not be assigned new value within the pro-
gram. To change the assigned value to a macro, it should be redefined by using #define
preprocessor.
✞
#include <stdarg.h>
2 #define MAX_NO 100
4 int main () {
printf("Maximum Nos is %d.n", MAX_NO);
6 #define MAX_NO 10
printf("Maximum Nos is %d.n", MAX_NO);
8 MAX_NO =50; // Illegal assignment . Shows error
printf("Maximum Nos is %d.n", MAX_NO);
10 return 0;
}
✌
✆
Example for preprocessor #define is given below
✞
1 #include <stdio.h>
#define getmax(a,b) ((a) >(b)?(a):(b))
3
int main () {
5 int y;
y = getmax (5, 2);
7 printf("The max value is %d.", y);
return 0;
9 }
✌
✆
✞
The max value is 5.
✌
✆
Use of #define function must be used carefully when the defined value is to be used in
mathematical expression. See the example below:
✞
1 #include <stdio.h>
#define PI 3.142857143 /* First form of defining macro.*/
3
int main () {
5 double i = 2 * PI / 3;
printf("i is %lf", i);
7 return 0;
208 Basic C
}
✌
✆
The expression line of above example
✞
double i = 2 * PI / 3;
✌
✆
The ‘PI’ is replaced by the macro value ‘3.14’ as
✞
1 double i = 2 * 3.142857143 / 3;
✌
✆
And the program gives result
✞
i is 2.095238
✌
✆
Now, see the example shown below, in which the ‘PI’ macro value is changed in rational
form even though its numerical value is same.
✞
1 #include <stdio.h>
3 #define PI 22 / 7 /* Rational form . */
/*Here , 22/7 is equal to 3 numerically */
5
int main () {
7 double i = 2 * PI / 3;
printf("i is %lf", i);
9 return 0;
}
✌
✆
This form of defining a value is wrong. See the reason in following lines. Assume that,
‘PI’ is defined as shown below
✞
#define PI 22 / 7
✌
✆
When preprocessor is replaced by its expression, the expression i becomes as
✞
1 double i = 2 * PI / 3;
✌
✆
At the time of compilation, preprocessor value of PI is used as 3 rather than 3.142857143.
Now, the value of i becomes
✞
1 double i = 2 * 3 / 3;
✌
✆
On solving this expression, the final result thus obtained is 2, which is not what we
expected.
✞
i is 2.000000
✌
✆
For desired output, proprocessor PI should be defined as (float)22/7 instead of 22/7.
See the modified form of above example.
1.10. PROCEDURES & FUNCTIONS 209
✞
1 #include <stdio.h>
3 #define PI (float) 22 / 7
5 int main () {
double i = 2 * PI / 3;
7 printf("i is %lf", i);
return 0;
9 }
✌
✆
✞
i is 2.095238
✌
✆
The preprocessors may be defined either before or after the header inclusion. In both
cases, output is same.
✞
1 #define NOS 10
3 #include <stdio.h>
5 int main () {
printf("%d",NOS);
7 }
✌
✆
✞
10
✌
✆
ANSI C defines some useful preprocessor macros and variables, also called “magic con-
stants”.
✞
1 __ FILE __ => The name of the current file , as a string literal.
__ LINE __ => Current line of the source file , as a numeric literal .
3 __ DATE __ => Current system date , as a string.
__ TIME __ => Current system time , as a string.
5 __ TIMESTAMP __ => Date and time (non - standard ).
__ cplusplus => undefined when your C code is being compiled by a C
compiler .
7 __ func __ => Current function name of the source file , as a string.
✌
✆
A simple example for using of preprocessors is derived in three parts. Main part, sum
part and preprocessors for sum part. Following is the code of ‘sum.h’ preprocessor
✞
1 #ifndef SUM_H
#define SUM_H
3 #ifdef __cplusplus
extern "C" {
5 #endif
/* function identifier for sum_f() defined in sum.c*/
7 int sum_f(int a, int b);
#ifdef __cplusplus
9 }
210 Basic C
#endif
11 #endif /* SUM_H */
✌
✆
Codes of sum function is define in the file ‘sum.c’.
✞
1 /* sum_f() function for adding two numbers */
int sum_f(int a, int b) {
3 int c;
c = a + b;
5 return c;
}
✌
✆
Main function for calling a procedure is defined in ‘main.c’ file as
✞
#include <stdio.h>
2 /* sum.h header contains sum_f() function *
* that should be indentified and called. */
4 #include "sum.h"
6 int main (void ){
int a=2,b=3;
8 /* sum_f() function is called from *
*sum.c and identified via sum.h */
10 int c=sum_f(a,b);
printf("The sum of 2 and 3 is %d.",c);
12 return 0;
}
✌
✆
When program is compiled and run the output is
✞
The sum of 2 and 3 is 5.
✌
✆
If a macro produces multiple statements, or declares variables, it can be wrapped in
a do { ... } while(0) loop, with no terminating semicolon. This allows the macro to be
used like a single statement in any location.
✞
1 #define FREE (p) free (p); p = NULL ; /* Bad practice .*/
#define FREE (p) do { free (p); p = NULL ; } while(0) /* Good
practice .*/
✌
✆
1.10.7 Type Converter
Following is an example of string to integer conversion.
✞
#include <stdio.h>
2 #include <string.h>
4 int main (int argc , char *argv [ ]) {
char st [10] = "This ";
6 printf("String ’%s’ = integer %d.n", st , (int) st);
1.11. PARSING ARGUMENTS 211
return 0;
8 }
✌
✆
✞
String ’This ’ = integer 2280640.
✌
✆
1.11 Parsing Arguments
When a program is being executed via another program internally, arguments are required
to be passed to the executable ie the program. These arguments are considered as inputs
for the executable. To pass the values we define main() function as
✞
1 int main (int argc , char *argv [ ])
✌
✆
Here argc counts the number of arguments in an array and argv assigns the values to
each respective counter.
✞
1 #include <stdio.h>
#include <string.h>
3 #include <stdlib.h>
5 /* main function is modified according to*
*receive the arguments in command line */
7 int main (int argc , char *argv [ ]) {
int argnum = 0;
9 /* Starting from zero */
while (argc > ++ argnum)
11 printf("Argument %d of arguments %d is %c.n",
argnum ,
13 argc ,
*argv [argnum ]);
15 exit ( EXIT_SUCCESS );
}
✌
✆
After compiling and executing the executable as
✞
executable .exe a b c
✌
✆
Output is
✞
Argument 1 of supplied four arguments is a.
Argument 2 of supplied four arguments is b.
Argument 3 of supplied four arguments is c.
✌
✆
Here executable.exe in command-line is also considered as an argument. This is why
there are four arguments and first argument, ie 0th
argument, is executable.exe itself and
rest of the arguments are a, b and c respectively. An other example is given below
212 Basic C
✞
1 #include <stdio.h>
3 int main (int argc , char ** argv ) {
size_t i;
5
for (i = 0; i < argc ; i++) {
7 /* get all the arguments as options *
*and initialize option pointer . */
9 char const *option = argv [i];
/* Get first character of an option argument */
11 if (option [0] == ’-’) {
/*If first character of an option argument *
13 *is ’-’, then following character is a flag */
printf("Flagged option.n");
15 /* get the second character of an option argument .*/
switch (option [1]) {
17 /*If second char of an option argument *
*is ’e’, then print encryption */
19 case ’e’:
printf("You have chosen %c:ENCryption . n",
option [1]) ;
21 break;
/*If second char of an option argument *
23 *is ’d’, then print decryption */
case ’d’:
25 printf("You have chosen %c:DECryption . n",
option [1]) ;
break;
27 /*If second char of an option argument *
*is ’f’, then print filename */
29 case ’f’:
printf("Your have chosen file name %c.n",
option [1]) ;
31 break;
/* other wise */
33 default :
printf("I can not understand your option %sn",
option);
35 break;
}
37 } else {
printf("No Flagged Options .n");
39 }
}
41 return 0;
}
✌
✆
When above example is compiled and executed like
✞
executable .exe -e -f
✌
✆
1.11. PARSING ARGUMENTS 213
The output at console is
✞
No Flagged Option.
Flagged Option.
You have chosen e:ENCryption .
Flagged Option.
You have chosen filename f.
✌
✆
The first output “No Flagged Option” is appeared at the console at first as ‘exe-
cutable.exe’ is considered as first parsing argument and it is not prefixed with ‘–’. Using
array and pointer we do reverse to a parsed string via command line is given below.
✞
1 #include <stdio.h>
#include <stdlib.h>
3 /* String Length*/
#define SLen 4
5
int main (int argc , char *argv [ ]) {
7 /* Get the commandline string*/
char *name = argv [1];
9 char nameR [10];
int i;
11 for (i = 0; i < SLen ; i++)
/* Store each character of string in array*/
13 nameR[i] = name [i];
15 for (i = 4; i > 0; --i)
/* Print each character of stored string in array*/
17 printf("%c", nameR[i - 1]);
exit ( EXIT_SUCCESS );
19 }
✌
✆
Similarly the string length of given string can also be obtain by using following example
✞
1 #include <stdio.h>
3 int main (int argc , char *argv [ ]) {
if (argv [1] == NULL ) {
5 printf("Use <utility .exe > <string in quote or double
quote >.n");
exit (0);
7 }
/* Get the commandline string*/
9 char *name = argv [1];
int i = 0;
11 while (name [i] != NULL )
i++;
13 printf("The length of string is %d", i);
return 0;
15 }
✌
✆
214 Basic C
1.11.1 Array To Integer
atoi() function is used to convert an array into integer. This function is very useful for
the conversion of number arguments passed as array or pointer into integer value. The
use of syntax is explained in the following example.
✞
1 #include <stdio.h>
#include <stdlib.h>
3
int main (int argc , char *argv [ ]) {
5 if (argv [1] == NULL ) {
printf("Use <utility .exe > <string >.n");
7 exit (0);
}
9 int i;
i = atoi (argv [1]) ;
11 printf("Array to integer is %d.", i);
exit ( EXIT_SUCCESS );
13 }
✌
✆
Without atoi(), we can also convert an array into integer by using simple mathematics
as explained in the following example.
✞
1 #include <stdio.h>
3 int main () {
char intg [ ] = "1234 ";
5 int i = 0, res = 0;
/* Here res must be initialized . Otherwise *
7 *product of res and 10 shall be null value*/
while (intg [i] != ’0’) {
9 /* Product of res with 10. res must not be null .*
* (intg [i] % 48) is used to convert integer *
11 * charcode into integer value. Charcode of 0 is*
* 48. Similarly , charcode of 1 is 49 and so on */
13 res = res * 10 + (intg [i] % 48);
i++;
15 }
printf("%dn", res);
17 return 0;
}
✌
✆
✞
1234
✌
✆
We can also used pointers for array to integer conversion. Above example is modified as
it is given below:
✞
1 #include <stdio.h>
3 int main () {
char *intg = "1234 ";
1.12. MATHEMATIS 215
5 int i = 0, res = 0;
/* Here res must be initialized . Otherwise *
7 *product of res and 10 shall be null value*/
while (* intg != ’0 ’) {
9 /* Product of res with 10. res must not be null .*
* (intg [i] % 48) is used to convert integer *
11 * charcode into integer value. Charcode of 0 is*
* 48. Similarly , charcode of 1 is 49 and so on */
13 res = res * 10 + (* intg % 48);
intg ++;
15 }
printf("%dn", res);
17 return 0;
}
✌
✆
atoi() function is used to convert an integer array into integer value. Integer value “1234”
as string is stored in memory as a group of characters. Each character is one byte long.
1 2 3 4
i :
Value at byte :
00000001 00000010 00000011 00000100
Integer value “1234” in numeric form is stored in 4 bytes long memory space, allocated
for solely storing of integer.
i :
Num value :
00000000 00000000 00000100 11010010
1234
1.12 Mathematis
In C programming addition, subtraction, multiplication and division mathematical op-
erators can be directly used. Modulus is another mathematical operators that gives the
remainder value. Application of these operators are a + b, a − b, a ∗ b, a/b and a%b
respectively.
✞
#include <stdio.h>
2 #include <string.h>
int a, b;
4
int main (void ) {
6 int a = 5;
int b = 2;
8 int add = a + b;
int sub = a - b;
10 int mul = a*b;
int div = a / b;
12 int mod = a % b;
216 Basic C
printf("Addition of %d and %d is : %d n", a, b, add);
14 printf("Subtraction of %d and %d is : %d n", a, b, sub);
printf("Multiplication of %d and %d is : %d n", a, b, mul);
16 printf("Division of %d and %d is : %d n", a, b, div);
printf("Modulus of %d and %d is : %d n", a, b, mod);
18 return 0;
}
✌
✆
Output of above program is
✞
Addition of 5 and 2 is : 7
Subtraction of 5 and 2 is : 3
Multiplication of 5 and 2 is : 10
Division of 5 and 2 is : 2
Modulus of 5 and 2 is : 1
✌
✆
A pointer can also be used in the addition, subtraction, multiplication and division of
two or more numbers.
✞
1 #include <stdio.h>
3 func (int *i, int*j) {
*i = *i * *i;
5 *j = *j* *j;
}
7
main () {
9 int i = 5, j = 2;
func (&i, &j);
11 printf("%d %d", i, j);
return 0;
13 }
✌
✆
✞
25, 4
✌
✆
1.12.1 Trigonometric Functions
“math.h” preprocessor file provides the mathematical functions that can be used directly
in the program. Some of them are defined in following sections.
cos, sin & tan
The cos, sin, and tan functions return the cosine, sine, and tangent of the argument,
expressed in radians. The domain of arguments of sin, cos and tan are [−π/2, π/2], [0, π]
and [−π/2, π/2] respectively. The numerical range of sin, cos and tan are [−1, 1], [−1, 1]
and [−∞, ∞].
✞
1 #include <math .h>
double cos(double x);
1.12. MATHEMATIS 217
3 double sin(double x);
double tan(double x);
✌
✆
A simple example is
✞
#include <stdio.h>
2 #include <math .h>
4 int main (void ) {
printf("Cosine at 22/7 radian is : %f n", cos (22/7));
6 printf("Sine at 22/7 radian is : %f n", sin (22/7));
printf("Tangent at 22/7 radian is : %f n", tan (22/7));
8 return 0;
}
✌
✆
✞
Cosine at 22/7 radian is : -0.989992
Sine at 22/7 radian is : 0.141120
Tangent at 22/7 radian is : -0.142547
✌
✆
Solved Problem 1.8 A right angle triangle having base 20cm and height h. The angle of
triangle facing to side h is 30◦
, then find the height of the triangle.
Solution We know that in right angle triangle, one angle is 90◦
. If angle facing to the
side of hcm is 30◦
then
tan 30◦
=
h
b
=
h
20
It gives, the height of the triangle h = 20/
√
3cm.
✞
1 #include <stdio.h>
#include <math .h>
3 #define PI 3.14
5 double DtoR (int x) {
return x * PI / 180;
7 }
9 int main () {
double h;
11 double b = 20.0;
int th = 30; /*in degree */
13 h = b * tan(DtoR (th));
printf("The height of the triangle is %lf", h);
15 return 0;
}
✌
✆
✞
The height of the triangle is 11.539928
✌
✆
218 Basic C
acos, asin & atan
The acos() functions return the arccosine of their arguments in radians, and the asin()
functions return the arcsine of their arguments in radians. All functions expect the
argument in the range [−1, +1]. The arccosine returns a value in the range [0, π]; the
arcsine returns a value in the range
h
−
π
2
,
π
2
i
. The atan() returns their argument value
in radian in the range
h
−
π
2
,
π
2
i
. Method of use of inverse function in following systems.
✞
1 #include <math .h>
double asin (double x);
3 double acos (double x);
double atan (double x);
✌
✆
A simple example is
✞
#include <stdio.h>
2 #include <math .h>
4 int main (void ) {
printf("Arc cosine at argument 0.5 is : %f n", acos (0.5));
6 printf("Arc sine at argument 0.5 is : %f n", asin (0.5));
printf("Arc tangent at argument 1.5 is : %f n", atan (1.5));
8 return 0;
}
✌
✆
✞
Arc cosine at argument 0.5 is : 1.047198
Arc sine at argument 0.5 is : 0.523599
Arc tangent at argument 1.5 is : 0.982794
✌
✆
cosh, sinh & tanh
The cosh(), sinh() and tanh() functions compute the hyperbolic cosine, the hyperbolic
sine and the hyperbolic tangent of the argument respectively.
✞
1 #include <math .h>
double cosh (double x);
3 double sinh (double x);
double tanh (double x);
✌
✆
A simple example is
✞
#include <stdio.h>
2 #include <math .h>
4 int main (void ) {
printf("Hyperbolic cosine of 0.5 is : %f n", cosh (0.5));
6 printf("Hyperbolic sine of 0.5 is : %f n", sinh (0.5));
printf("Hyperbolic tangent of 1.5 is : %f n", tanh (1.5));
8 return 0;
1.12. MATHEMATIS 219
}
✌
✆
✞
Hyperbolic cosine at argument 0.5 is : 1.127626
Hyperbolic sine at argument 0.5 is : 0.521095
Hyperbolic tangent at argument 1.5 is : 0.905148
✌
✆
acosh, asinh & atanh
The acosh() functions compute the inverse hyperbolic cosine of the argument. A domain
error occurs for arguments less than 1. The asinh() and atanh() functions compute the
inverse hyperbolic sine and inverse hyperbolic tangent of the argument respectively.
✞
1 #include <math .h>
double acosh(double x);
3 double asinh(double x);
double atanh(double x);
✌
✆
A simple example is
✞
#include <stdio.h>
2 #include <math .h>
4 int main (void ) {
printf("Hyp inverse cosine of 0.5 is : %f n", acosh (0.5));
6 printf("Hyp inverse sine of 0.5 is : %f n", asinh (0.5));
printf("Hyp inverse tangent of 1.5 is : %f n", atanh (1.5));
8 return 0;
}
✌
✆
✞
Hyperbolic inverse cosine at argument 0.5 is : nan
Hyperbolic inverse sine at argument 0.5 is : 0.481212
Hyperbolic inverse tangent at argument 1.5 is : nan
✌
✆
1.12.2 Logarithm Function
Exponential & Logarithm
exp() represents the exponential of a value x with base ‘e’. log() represents the logarithm
of a value in natural base ‘e’.
✞
1 #include <math .h>
double exp(double x);
3 double log(double x);
✌
✆
A simple example is
220 Basic C
✞
1 #include <stdio.h>
#include <math .h>
3
int main (void ) {
5 printf("Exponential of 0.5 is : %f n", exp (0.5));
printf("logarithm of 0.5 at base 10 is : %f n", log (0.5));
7 return 0;
}
✌
✆
✞
Exponential of 0.5 is : 1.648721
logarithm of 0.5 at base 10 is : -0.693147
✌
✆
1.12.3 Arithmetic Function
In C, symbol ˆ does not represent to power but presents to XOR bitwise operation. In
‘math.h’ preprocessor provides the power operation via pow() function.
Power
pow() accepts two values. First is base, (b) and second is exponent, (e). Mathematically
this function is equivalent to
Y = be
This function is used as
✞
double pow(double x, double y);
✌
✆
A table consisting cube of first 10 integers ranging from 1 to 10 is shown below. The
formula used is
y = i3
Here, 3 is exponent or power and i is base.
Base Exp Result, y
1 3 1
2 3 8
3 3 27
4 3 64
5 3 125
6 3 216
7 3 343
8 3 512
9 3 729
1.12. MATHEMATIS 221
A simple example is
✞
1 #include <stdio.h>
#include <math .h>
3
int main (void ) {
5 printf("Power of 2 on base 3 is : %f n", pow(3, 2));
return 0;
7 }
✌
✆
✞
Power of 2 on base 3 is : 9.000000
✌
✆
Square Root
sqrt() returns the square root of a given value. Mathematically it is represented as
y =
√
i
Where, i is any number. The syntax of this function is given below:
✞
1 double sqrt (double x);
✌
✆
A table consisting square root of few specific numbers is given below. The formula used
is
y =
√
i
Integer Squre Root, y
1 1.00
2 1.41
3 1.73
4 2.00
5 2.24
6 2.45
7 2.65
8 2.83
9 3.00
A simple example is
✞
1 #include <stdio.h>
#include <math .h>
3
222 Basic C
int main (void ) {
5 printf("Square root of 1.45 is : %f n", sqrt (1.45));
return 0;
7 }
✌
✆
✞
Square root of 1.45 is : 1.204159
✌
✆
Floor
floor() function accepts a real number. Result of floor value of a real number is, either
perfect integer positive or negative as the case may be which is either equal to or less
than the given number. Its syntax is given by
✞
1 double floor(double x);
✌
✆
-3 -2 -1 0 1 2 3
b
−1.5
bc
floor(−1.5)
b
1.5
bc
floor(1.5)
A table consisting few positive and negative numbers with their corresponding floor value,
is given below.
Real Number floor(r)
-2.25 -3.00
-2.75 -3.00
-3.00 -3.00
2.25 2.00
2.75 2.00
3.00 3.00
A simple example is
✞
1 #include <stdio.h>
#include <math .h>
3
int main (void ) {
5 printf("Floor of 1.45 is : %f n", floor (1.45));
printf("Floor of -1.45 is : %f n", floor( -1.45) );
7 return 0;
}
✌
✆
1.12. MATHEMATIS 223
✞
Floor of 1.45 is : 1.000000
Floor of -1.45 is : -2.000000
✌
✆
Ceiling
ceil() function accepts a real number. Result of ceiling value of a real number is the
perfect integer, either positive or negative as the case may be, which is either equal to or
greater than the given number.
✞
double ceil (double x);
✌
✆
-3 -2 -1 0 1 2 3
b
−1.5
bc
floor(−1.5)
bc
ceil(−1.5)
-3 -2 -1 0 1 2 3
b
1.5
bc
floor(1.5)
bc
ceil(1.5)
A table consisting few positive and negative numbers with their corresponding ceiling
value, is given below.
Real Number ceil(r)
-2.25 -2.00
-2.75 -2.00
-3.00 -3.00
2.25 3.00
2.75 3.00
3.00 3.00
A simple example is
✞
1 #include <stdio.h>
#include <math .h>
3
int main (void ) {
5 printf("Ceil of 1.4855 is : %f n", ceil (1.4855) );
printf("Ceil of -1.4855 is : %f n", ceil ( -1.4855) );
7 return 0;
}
✌
✆
224 Basic C
✞
Ceil of 1.4855 is : 2.000000
Ceil of -1.4855 is : -1.000000
✌
✆
Rounds Off
round() function rounds off a fraction number to its nearest perfect integer. The fractional
part about which number is rounded-off is 0.5. This definition is advanced with following
rules.
1. If non-significant digit is less than 5 and is to be rounded off, the previous digit
does not change and non-significant digit is simply dropped. For example 2.301
is significant upto the second place of the decimal then digit 1 is simply dropped
and number is rounded off to 2.30. Similarly 2.304 is rounded off upto two place of
decimal as 2.30.
2. If non-significant digit is greater than 5 and is to be rounded off, the previous digit
(left side digit) is raised by 1 and non-significant digit is dropped. For example 2.306
is significant upto the second place of the decimal then digit 6 is simply dropped
and previous digit (left side digit) 0 is raised by 1 and number is rounded off to
2.31.
3. If the rounding off digit is greater than 5, rounding off digit is simply dropped when
the previous digit (left side digit) is even. For example, when 2.3546 is rounded off,
result is 2.354.
4. If the rounding off digit is greater than 5, rounding off digit is dropped and previous
digit (left side digit) is raised by 1 when the previous digit (left side digit) is odd.
For example, when 2.3576 is rounded off, result is 2.358.
5. In mathematics and specially in pure science, the large numbers are mostly written
in scientific notation form. Hence these numbers are rounded-off upto significant
digits. To round-off a large number upto n digits, the rounding-off process is always
started from leftmost non-zero digit. For example start process from 2 in 2500 and
from 3 in 0.0325.
6. Keep n significant digits and replace rest of digits with zeros.
7. Write number in scientific notation, i.e. a × 10±b
form, where a and b are real and
significant numbers.
8. Round off mantissa upto the last significant digit. For example 0.2336 can be written
as 2.336 × 10−1
in scientific notation and if there are only three significant digits
then third significant digit becomes 4 and number becomes 2.34 × 10−1
. Rest of
digits are dropped.
The syntax of this function is given below:
✞
double round(double x);
✌
✆
1.12. MATHEMATIS 225
round() function in math library of C is loosely based on the basic rule of round-off.
Hence in each case, if rounding-off digit is equal to or larger than 5, then previous digit
is raised by 1. A simple example is
✞
1 #include <stdio.h>
#include <math .h>
3
int main (void ) {
5 printf("Rounding of 1.4 is : %f n", round (1.4));
printf("Rounding of 1.6 is : %f n", round (1.6));
7 return 0;
}
✌
✆
✞
Rounding of 1.4 is : 1.000000
Rounding of 1.6 is : 2.000000
✌
✆
0 1 2 3
b
1.6
bc
round(1.6)
b
1.4
bc
round(1.4)
Round off negative numbers in C program is given below:
✞
#include <stdio.h>
2 #include <math .h>
4 int main (void ) {
printf("Rounding of -1.4 is : %f n", round( -1.4));
6 printf("Rounding of -1.6 is : %f n", round( -1.6));
return 0;
8 }
✌
✆
✞
Rounding of -1.4 is : -1.000000
Rounding of -1.6 is : -2.000000
✌
✆
-3 -2 -1 0
b
−1.6
bc
round(−1.6)
b
−1.4
bc
round(−1.4)
Rounding off a number cause rounding off errors. For example a real number 2.56889 is
actual real number is which is rounded off upto 4th
decimal place. It becomes 2.5689.
Now the difference of the two values is 2.56889 − 2.5689 = −0.00001. It is error arises
due to rounding off a real number.
226 Basic C
1.12.4 Float Point Arithmetic
A float or a double has three components, (i) a sign bit, (ii) exponent and (iii) mantissa.
A floating point number is written as
f = ±m × b±e
Here, m is mantissa of the number, b is base, i.e. 2 in IEEE-754 standards. e is exponent
of the floating point number. In this section we shall use single point (float) floating
numbers. A float data type number is 32 bits long and has three components, (i) a sign
bit (first bit from left side), (ii) an exponent (next 8 bits from left side) and (iii) a mantissa
(rest of 23 bits). The exponent is an excess-127 binary notation. This binary number
is also known as exponent bias.
Binary Equivalent Desired Exponent
· · · · · ·
01111100 -3
01111101 -2
01111110 -1
01111111 0
10000000 1
10000001 2
10000010 3
· · · · · ·
In this notation, binary number 01111111, equivalent to decimal 127 is a binary ex-
ponent equivalent to decimal 0. The next binary exponent i.e. sum of binary 01111111
and bit 1 represents to exponent equivalent to decimal 1 (equivalent to binary 10000000).
Similarly, subtraction of bit 1 from 01111111 represents to exponent equivalent to deci-
mal −1 (equivalent to binary 01111110). Remember that for binary equivalent form of
floating point numbers, base is 2, i.e. exponent binary 01111111 is equal to in decimal
form of 20
, exponent binary 10000000 means 21
, exponent binary 01111110 means 2−1
and so on.
125 126 127 128 129
01111101 01111110 01111111 10000000 10000001
−2 −1 0 1 2
2−2
2−1
20
21
22
Decimals
Excess-127
e-Line
2e
Value
1.12. MATHEMATIS 227
The decimal exponent equivalent to binary exponent is obtained by subtracting 01111111
from the given binary exponent. The mantissa binary numbers are solved from left side
to right side. Here, we are dealing with binary fractions, so the leftmost mantissa bit
means 2−1
, the next right bit has meaning of 2−2
and so on. The place values of mantissa
bits from left side to right side are 2−1
, 2−2
, 2−3
etc. The first bit of a non-zero binary
significant is always 1. Hence mantissa in fractions is given by
M = 1 +
n
X
i=1
biti × 2−i
Here, i is ith
bit counted from left hand side to right hand side in mantissa part. n is
total number of significant digits in mantissa.
Illustrated Example Assume a floating point representation ‘0 0111 1100 0000 0000
0000 0000 0000 000’ shown in binary form. The sign bit of this binary number is ‘0’,
hence it is positive value. The exponent binary number is 01111100 and mantissa number
is 0000 0000 0000 0000 0000 000. Note that if left most digit of the binary exponent part
of floating point number is ‘0’, then exponent is obtained by subtracting 01111111 from
the given binary exponent. Here, binary subtraction of
01111100
-01111111
-00000011
which is equivalent to decimal −3. The exponent value is −3. The mantissa part is
all zero, hence
M = 1 +
23
X
i=1
biti × 2−i
gives mantissa ‘1’. Now, the number is
r = 1 × 2−3
It gives 0.125.
Illustrated Example Assume a floating point representation ‘0 1010 0110 1101 0001
1010 1001 0100 101’ shown in binary form. The sign bit of this binary number is ‘0’,
hence it is positive value. The exponent binary number is 10100110 and mantissa number
is 1101 0001 1010 1001 0100 101. Note that, if the left most digit is of binary exponent is
‘1’, then exponent is obtained by subtracting 01111111 from the given binary exponent.
Here, binary subtraction of
10100110
-01111111
00100111
228 Basic C
which is equivalent to decimal 39. The exponent value is 39. The mantissa part is
M = 1 +
23
X
n
bitn × 2−n
gives mantissa ‘1.818989396095270’. Now, the number is
r = 1.818989396095270 × 239
It gives 999999995904. Numerical programming languages use double type floating point
mathematics. Therefore each number is denoted as float point, i.e. 1.0 as 1.000000, 0.5 as
0.500000. Sometime, even zero is represented as 2.5×10−18
or as 13.2×10−19
etc. where
these values are very very small and are close to zero. Here zero is taken as comparative
value rather than absolute value. For example, sometimes, in numerical calculations,
identity matrix is represented as
c programming
c programming
c programming
c programming
c programming
c programming
1 3.5 × 10−12
35 × 10−12
1
c programming
c programming
c programming
c programming
c programming
c programming
Operators in Float Points Arithmetic
Normally, all the arithmetic operators may be used in floating point arithmetic. In float
point arithmetic, mixing of two different floating points are allowed. A float or double
data type value can be used with int data type value. The result of mixed data type
values is extended to match the precision of the more precise data type value. Floating
point division does not discard the fractional part and produce round off errors.
✞
#include <stdio.h>
2
int main (void ) {
4 printf("2 + 2.0 is %fn", 2 + 2.0) ;
printf("2 - 2.0 is %fn", 2 - 2.0) ;
6 printf("2 / 2.0 is %fn", 2 / 2.0) ;
printf("2 * 2.0 is %fn", 2 * 2.0) ;
8 return 0;
}
✌
✆
✞
2 + 2.0 is 4.000000
2 - 2.0 is 0.000000
2 / 2.0 is 1.000000
2 * 2.0 is 4.000000
✌
✆
Few operators do not work with floating-point datatypes., i.e. real numbers. These are
% (modulo) and all of the bitwise operators, like ∼, <<, >>, &, ˆ, and |.
✞
#include <stdio.h>
2
int main (void ) {
1.12. MATHEMATIS 229
4 /* Will show errors*/
printf("2 % 2.0 is %fn", 2 % 2.0) ;
6 /* Will show errors*/
printf("2 ^ 2.0 is %fn", 2 ^ 2.0) ;
8 return 0;
}
✌
✆
An int data type value can be converted into floating point type by casting it.
✞
1 #include <stdio.h>
3 int main (void ) {
printf("2 is %fn", (float) 2);
5 printf("2 is %lfn", (double) 2);
return 0;
7 }
✌
✆
✞
2 is 2.000000
2 is 2.000000
✌
✆
Few of the floating values are shown in the following table.
Float Decimal Binary Form
0 0 0 00000000 00000000000000000000000
-0 -0 1 00000000 00000000000000000000000
0.1 0.10000000149011612 0 01111011 10011001100110011001101
0.125 0.125 0 01111100 00000000000000000000000
0.25 0.25 0 01111101 00000000000000000000000
1 1 0 01111111 00000000000000000000000
2 2 0 10000000 00000000000000000000000
1e+12 999999995904 0 10100110 11010001101010010100101
inf inf 0 11111111 00000000000000000000000
-inf -inf 1 11111111 00000000000000000000000
nan nan 0 11111111 10000000000000000000000
A value is said to be positive infinity (0×7f800000) when its sign bit is 0 and exponent
is 0×ff and all mantissa bits are 0. Similarly, a value is said to be negative infinity
(0×ff800000) when its sign bit is 1 and exponent is 0×ff and all mantissa bits are 0.
A not-a-number (0×7fc00000) case arises when sign bit of floating point number is 0,
exponent is 0×ff and mantissa is 0×400000.
230 Basic C
Astray Result
Sometimes when a float data type number is printed in output console, it gives strange
result. Like 3.1 prints as 3.0999999. Its reason is that most hardware uses base 2 for
floating-point numbers rather than base 10. All the fractions in base 10 (decimal form) can
not be represented in base 2 (binary form). This is why, decimal fraction 3.1 sometimes
printed as 3.0999999.
Double Floating Point
A double is 64 bits long and has three components, (i) a sign bit (first bit from left side),
(ii) exponent (next 11 bits from left side) and (iii) mantissa (rest of 52 bits). A double
point floating point number is written as
f = ±m × b±e
Here, m is mantissa of the number, b is base either ‘10’ or ‘e’ or ‘2’ and n is exponent
of the floating type number. In computers, the base is ‘2’. Binary number 1111111111
equivalent to decimal 1023 is used as Exponent bias.
1.12.5 Zero Crossing
A function is said to be zero-crossing function if its sign changes when its independent
variable crosses to zero in a number line. For example
f(x) = x; for − 1 < x < 1
changes its sign when x crosses to zero. Similarly
f(x) = sin(x); for − 4 < x < 4
is also a zero crossing function which changes its sign when x crosses to zero. Zero crossing
has emmence importance in electrical and computer science.
Limit At Zero
In mathematics, limit is a finite value of a continuous function at a given point. It is
represented as
lim
x→a
f(x) = k
Where k is fininte value of the function at given point ‘a’. If ‘a’ is zero then some functions
behave strangly and do not give finite value, i.e. converging value at the point of limit.
Assume a function, here y = sin(x), which converges to a finite value at point ‘0’
lim
x→0
y = lim
x→0
sin(x) = 0
x
y
b
(0, 0)
1.12. MATHEMATIS 231
Contrast to these types of functions, fraction functions diverge to ∞ when x → 0. See
the following limit equation for function y = 1/x,
lim
x→0
y = lim
x→0
1
x
= ∞
Now, it is not possible to use this function with other functions in mathematical op-
erations. To avoid it, we take approaching limit to point ‘0’ of the function as given
below:
lim
x→0
y = lim
x→0
1
x
= ∞; when [−∞, 0) < x < (0, ∞]
x
y
b
(0, 0)
Here, ±∞ is acceptable as 1/ ± ∞ = 0, which is a finite value.
1.12.6 Random Number Generator
Following C program is used to generate random numbers. A user defined seed control
the initial random number and subsequent random numbers are used as seed for next
random number. This program given first five random number against a seed value.
✞
#include <stdio.h>
2 extern void SeedToNew (unsigned int x);
extern int MyRand(void );
4
int main (void ) {
6 int count;
unsigned seed ;
8 printf("Please enter seed .n");
while (scanf("%u", &seed ) == 1) {
10 SeedToNew (seed );
for (count = 0; count < 5; count ++)
12 printf("%hdn", MyRand());
printf("Please enter newSeed (q to quit ):n");
14 }
printf("Done n");
16 return 0;
}
18
232 Array & Pointer
static unsigned long int newSeed = 1; /* the seed */
20
int MyRand(void ) {
22 newSeed = newSeed * 1103515245 + 12345;
return (unsigned int) (newSeed / 65536) % 32768;
24 }
26 void SeedToNew (unsigned int seed ) {
newSeed = seed ;
28 }
✌
✆
In the codes in line
✞
return (unsigned int) ( newSeed / 65536) % 32768;
✌
✆
The value 32768 is used to control the limits of the random number. If it is 10 then all
the random number will be within 0 to 10.
2.1. ARRAY 233
2Array & Pointer
2.1 Array
Arrays in C stores data in a single variable name with an index, also known as a subscript.
It is simply a list or ordered grouping for variables of the same type. Arrays often help a
programmer in organize collections of data efficiently and intuitively. A character array
takes one byte for each character while an integer array takes 4 bytes for one integer.
Other datatypes takes appropriate bytes to stores that data type value.
A B C D E F ‘0’
myStrA
Figure 2.1: Array of first six alphabetic characters stored in memory and pointed by
variable ‘myStrA’.
00000001 00000010
myNumA myNumA[0] myNumA[1]
Figure 2.2: Array of two integers pointed by variable ‘myNumA’ are stored in memory
as shown this figure. Each integer needs four bytes memory space.
2.1.1 Uni-Dimensional Array
Arrays are declared by two ways, (i) static and (ii) dynamic. Static arrays are declared
using square brackets containing size of array. Dynamic arrays are declared with pointers.
In static declaration, compiler creates space required for storing of data at declaration
and then returns the address of memory space created. In case of string, one extra
space for null terminator is also reserved. In case of dynamic declaration only address
of proposed memory space is returned where proposed data may be stored. It does not
reserve memory space. To create memory space, function malloc is used. Note that only
string arrays have terminating marker (0). Other type of arrays must be controlled by
array size. muArrays are declared and initialized like
✞
1 int numbers [6]; // array declared & space created
int point [6]={0 ,0 ,1 ,0 ,0 ,0}; // array declared , space
3 // created and initialized
✌
✆
234 Array & Pointer
Remember that the initialization of static array is take place alongwith its declaration.
Otherwise initialization of an array shows compile time error.
✞
1 char myS [];
myS="My String"; /* Illegal initialization .*/
3 // Actually , above action was copying of data to
// array , not initialisation . Copying of data done
5 // by copying character one by one in memory space
char myStr []="My String"; /* Legal initialization .*/
✌
✆
Initialisation of array with pointer after declaration is compiler dependent.
✞
#include <stdio.h>
2
int main () {
4 char *c = "This ";
c = "That ";
6 printf("%s", c);
return 0;
8 }
✌
✆
✞
That
✌
✆
The brackets ([ ]) identify ‘numbers’ or ‘points’ and the number enclosed in the brackets
indicates the number of elements in the array. An element of the array can be accessed by
its index number i.e. subscripts of the array. When square bracket symbol in static array
declaration does not contain size of array then it is called dynamic declaration of array.
Dynamic array declaration is permitted if it is initialised at the time of declaration. In
following example, each element of the array is accessed by its index number.
✞
1 #include <stdio.h>
3 int main (void ) {
int ix;
5 short anArray[ ] = {3, 6, 9, 12, 15};
for (ix = 0; ix < ( sizeof (anArray ) / sizeof ( short)); ++ix) {
7 printf("The array value is %d.n", anArray [ix]);
}
9 }
✌
✆
i0 i1 i2 i3 i4
3 6 9 12 15
anArray
Figure 2.3: Head integer value consumes 4 byte memory space. in represents to the index
of elements of array ‘days’. Total bytes of memory used to store data is 5 × 4 = 20.
2.1. ARRAY 235
In the above example, the size of the array was not explicitly specified. The compiler
knows the size of array from the initialized list. The size of ‘anArray’ is ‘5’ because
‘anArray’ has five elements. Addition of an additional element to the list will increase its
size to six. Static declaration of the size of an array, the array list will be overflow. To
overcome this problem sizeof expression is used as
✞
1 size = sizeof(anArray)/ sizeof(short)
✌
✆
As the sizeof expression in the for loop, the script is automatically adjusted to this
change. Designated initializer is allow to pick and choose the initialized elements. If the
last element of an array is initialized then in the initialization syntax of traditional C,
there is a requirement of initialization of every element preceding to the last one. An
array, if initialized, then each element value is index from 0 to n − 1, where n is size of
the array. For example,
✞
1 int count[] = {31, 28, 30, 29, 32, 27}; // array size is 6
✌
✆
has six elements. The element value at index 0 is 31, element value at index 1 is 28 and
so on. The index of array element may be redefined inside the array as the method given
in following syntax
✞
1 /* int count[] = {[<new index >]=< array element value >};*/
int count[] = {31, [2] = 28, 30, 29, 32, 27};
✌
✆
Here, the index of second element is 2, i.e. element shall be stored at third place of
memory of integer data type. Elements of an array are overridable, i.e. new element
value at index 4 can be override the old value of the element at the index 4 if any other
element is assigned the index value 4.
✞
#include <stdio.h>
2 #define MONTHS 12
4 int main (void ) {
int days [MONTHS] = {31, 28, [4] = 31, 30, 31, [1] = 29};
6 int i;
for (i = 0; i < MONTHS; i++)
8 printf("%2d %dn", i + 1, days [i]);
return 0;
10 }
✌
✆
In above program example, array ‘days’ has first element (at index position 0) 31, second
element (at index position 1) is 28. Next element, 30, of the array ‘days’ is declared for
index 4, i.e. for 5th
position. Next element is 30 in the array ‘days’. Its position shall
be next to the previous element, i.e. after 5th
position, therefore this element will be at
6th
position or at index position 5. Element for index position 6 is 31. Last element is
defined for index position 1. Hence previous element, 28, which was at the index position
1 shall be replaced by value 29. The final arrangement of the array data in the memory
shall be as shown in the below figure.
236 Array & Pointer
i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11
31 29 0 0 31 30 31 0 0 0 0 0
days
Figure 2.4: Arrangement of elements of array ‘days’ in memory. Here, each block rep-
resents to an integer data byte (i.e. group of four memory bytes). in represents to the
index of elements of array ‘days’.
✞
1 31
2 29
3 0
4 0
5 31
6 30
7 31
8 0
9 0
10 0
11 0
12 0
✌
✆
An array initialised with ‘[ ]’ is called expandable array. When an array is declared
without its size, compiler first count the array elements and then it grows the array upto
a size so that all the elements can stored in the array.
✞
/* Array with growing size . */
2 int days [ ] = {31, 28, [4] = 31, 30, 31, [1] = 29};
✌
✆
✞
#include <stdio.h>
2
int main (void ) {
4 int days [] = {31, 28, [4] = 31, 30, 31, [1] = 29};
int i;
6 printf("Size of array is %dn", sizeof (days ) / sizeof (int));
/* Here sizeof (days ) / sizeof (int) is not*
8 *grouped as ‘/’ higher precedence to ‘<’ */
for (i = 0; i < sizeof (days ) / sizeof (int); i++)
10 printf("%2d %dn", i , days [i]);
return 0;
12 }
✌
✆
✞
Size of array is 7
0 31
1 29
2 0
3 0
4 31
5 30
2.1. ARRAY 237
6 31
✌
✆
2.1.2 Multi-Dimensional Array
An array declaration in C is given by
✞
int myA[m][n];/*m rows and n cols .*/
✌
✆
If the size of integer type array is fixed as shown above, compiler reserves m× n× k bytes
memory. Here, k is size of variable data type. For integer it is 4 as integer is 4 bytes long
data type. Hence, memory size allocated for integer array of type m × n is 4mn. Assume
a 2 × 2 integer array as shown below
✞
1 int myA [2][2] = {
{10, 20},
3 {15, 2}
};
✌
✆
The memory allocated for this array is 2 × 2 × 4 = 16 bytes. As column size of this array
is 2, hence 8 bytes are taken in a group for two columns, in which each column uses 4
bytes for storing integer data. Remember that, in following figures, each cell represents
to one byte. This is why, an integer is represented here as a group of four bytes. It is
done, for convenient to calculate the number of bytes required to store an array data.
And in computer, the index counting is started from ‘0’ instead of ‘1’.
10 0 0 0 20 0 0 0
15 0 0 0 2 0 0 0
myA c0 c1
r0
r1
In above figure, the byte position of array data is shown into two rows and two column.
Practically above data is stored in memory as continuous data bytes.
10 0 0 0 20 0 0 0 15 0 0 0 2 0 0 0
myA
1st
row 2nd
row
1st
col 2nd
col 1st
col 2nd
col
From the above arrangement of data, in a multi-dimensional array, number of rows
may be constant or variable but number of columns must be constant. The reason is
that, elements of an array are arranged one by one sequentially, so if column size is not
fixed then pointer-to-array variable will not be able to identify the starting of next row
of the array. See the example below:
238 Array & Pointer
✞
#include <stdio.h>
2
int main () {
4 int i;
int myA [2][2] = {/* 2X2X4 =16 bytes */
6 {10, 20},
{15, 2}
8 };
printf("Size of array is %dn", sizeof (myA));
10 char *p = (char *) &myA; // Cast int into char ptr
for (i = 0; i < sizeof (myA); i++) {
12 printf("%d ", p[i]);// print all 16 bytes
}
14 return 0;
}
✌
✆
✞
Size of array is 16
10 0 0 0 20 0 0 0 15 0 0 0 2 0 0 0
✌
✆
Now, an array having two columns but dynamic rows is declared and assigned as the
syntax is given below:
✞
int myB[ ][2] = {
2 {10, 20},
{15, 2},
4 {1, 4}
};
✌
✆
The memory allocated for this array is dynamic. This array has two columns hence
memory is allocated in the multiple of 2 × 4 = 8 bytes. If there are two rows then
memory allocation will be expanded to 8 × 2 = 16 bytes. Similarly if there are three
rows then memory allocation will be expanded to 8 × 3 = 24 bytes and so on, subject to
memory sharing is not violated.
myA
10 0 0 0 20 0 0 0
15 0 0 0 2 0 0 0
1 0 0 0 4 0 0 0
c0 c1
r0
r1
r2
See the example below:
✞
1 #include <stdio.h>
2.1. ARRAY 239
3 int main () {
int i;
5 /* Array has fixed cols & dynamic rows */
int myB[ ][2] = {
7 {10, 20},
{15, 2},
9 {1, 4}
};
11 printf("Size of array is %dn", sizeof (myB));
char *p = (char *) &myB;
13 for (i = 0; i < sizeof (myB); i++) {
printf("%d ", p[i]);
15 }
return 0;
17 }
✌
✆
✞
Size of array is 24
10 0 0 0 20 0 0 0 15 0 0 0 2 0 0 0 1 0 0 0 4 0 0 0
✌
✆
An array having two rows and three columns is declared and initialized as shown in the
syntax given below:
✞
int two_d [2][3] = {{ 5, 2, 1 },
2 { 6, 7, 8 }};
✌
✆
Where [2] represents to the number of rows and [3] represents to the number of columns of
the two dimensional array. A three dimensional array is declared as given in the following
syntax:
✞
int myA[ ][3][2];
2 /* | | | *
* l r c */
✌
✆
This array has two columns (y-axis represented as ‘c’ here), three rows (x-axis represented
as ‘r’ here) and variable number of layers (z-axis represented as ‘l’ here). In C programs,
which contains three dimensional array, the z-axis (i.e. third dimension) is always outer-
most loop. Practically, three dimensional array is layers of two dimensional arrays. As
shown in the following figure, a 3 × 2 array is placed in four layers and collectively, they
form a 3 × 2 × 4 three dimensional array.
240 Array & Pointer
l0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
c0 c1
r0
r1
r2
l1
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
c0 c1
r0
r1
r2
l2
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
c0 c1
r0
r1
r2
l3
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
c0 c1
r0
r1
r2
A three dimensional array is arranged in patterns as shown in below figure.
myA
l0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
c0 c1
r0
r1
r2
l1
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
c0 c1
r0
r1
r2
The memory arrangement of three dimensional array is given in the following figure.
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
myA
r0 of l0 r1 of l0
c0 of r0 c1 of r0 c0 of r1 c1 of r1
Multi-dimensional array can be used to add, subtract and product (either dot or cross)
of two vectors or matrices. Following is an example using an array of 5 × 5 dimension.
This example requires 5 × 5 × 4 = 100 bytes.
✞
1 #include <stdio.h>
#define X 5
3 #define Y 5
5 int main (void ) {
int ix , iy;
7
short anArray[X][Y]; /* 100 bytes memory requirement .*/
9 for (ix = 0; ix < X; ++ix) {
for (iy = 0; iy < Y; ++iy) {
2.1. ARRAY 241
11 anArray[ix][ iy] = ix * iy;
};
13 }
for (ix = 0; ix < X; ++ix) {
15 for (iy = 0; iy < Y; ++iy) {
printf("%2dt", anArray[ix][iy]);
17 };
printf("n");
19 }
}
✌
✆
✞
0 0 0 0 0
0 1 2 3 4
0 2 4 6 8
0 3 6 9 12
0 4 8 12 16
✌
✆
Multidimentional array can be extended in matrix manipulations, additions, subtractions,
multiplications and divisions. In the following example, two matrices are added and
subtracted element-wise. The element-wise addition and subtraction is given by
Cij = Aij ± Bij
✞
1 #include <stdio.h>
3 /* Random number generator between 0 to 10.*/
int rand_num (int a, int b) {
5 return ((a * 97 + b*21) & 10);
}
7
int main () {
9 int i/* row*/,
j/* col*/;
11 int A [3][3]/* First Matrix*/,
B [3][3]/* Second Matrix*/,
13 C [3][3]/* Third Matrix*/;
printf("First Random Matrix is :n");
15 /* For each of three rows */
for (i = 0; i < 3; i++) {
17 /* There are three columns.*/
for (j = 0; j < 3; j++) {
19 /* Assign a random matrix elements .*/
A[i][j] = rand_num (i*j, j);
21 printf("%3dt", A[i][j]);
}
23 /* Print new line after completion of each row*/
printf("nn");
25 }
printf("nSecond Random Matrix is :n");
27 /* For each of three rows */
242 Array & Pointer
for (i = 0; i < 3; i++) {
29 /* There are three columns.*/
for (j = 0; j < 3; j++) {
31 /* Assign a random matrix elements .*/
B[i][j] = rand_num (i, i*j);
33 printf("%3dt", B[i][j]);
}
35 /* Print new line after completion of each row*/
printf("nn");
37 }
printf("nElementwise Addition of Matrix is :n");
39 /* For each of three rows */
for (i = 0; i < 3; i++) {
41 /* There are three columns.*/
for (j = 0; j < 3; j++) {
43 /* Add matrices elementwise .*/
C[i][j] = A[i][j] + B[i][j];
45 printf("%3dt", C[i][j]);
}
47 /* Print new line after completion of each row*/
printf("nn");
49 }
printf("nElementwise Subtraction of Matrix is :n");
51 /* For each of three rows */
for (i = 0; i < 3; i++) {
53 /* There are three columns.*/
for (j = 0; j < 3; j++) {
55 /* Subtract matrices elementwise .*/
C[i][j] = A[i][j] - B[i][j];
57 printf("%3dt", C[i][j]);
}
59 /* Print new line after completion of each row*/
printf("nn");
61 }
return 0;
63 }
✌
✆
✞
First Random Matrix is :
0 0 10
0 2 8
0 2 10
Second Random Matrix is :
0 0 0
0 2 10
2 8 2
Elementwise Addition of Matrix is :
0 0 10
0 4 18
2 10 12
Elementwise Subtraction of Matrix is :
0 0 10
2.1. ARRAY 243
0 0 -2
-2 -6 8
✌
✆
The vector and scalar products between two matrices can also be done. The dot product
of two matrices is given by
Cij = ~
Aij · ~
Bij
In the following example, dot products between to matrices is performed.
✞
#include <stdio.h>
2
/* Random number generator between 0 to 10.*/
4 int rand_num (int a) {
return ((a * 1011457789 + 12345) & 10);
6 }
8 int main () {
int i/* row*/,
10 j/* col*/;
int A [3][3]/* First Matrix*/,
12 B [3][3]/* Second Matrix*/,
C [3][3]/* Dot Matrix */;
14 printf("First Random Matrix is :n");
/* For each of three rows */
16 for (i = 0; i < 3; i++) {
/* There are three columns.*/
18 for (j = 0; j < 3; j++) {
/* Assign a random matrix elements .*/
20 A[i][j] = rand_num (i + j);
printf("%dt", A[i][j]);
22 }
/* Print new line after completion of each row*/
24 printf("nn");
}
26 printf("nSecond Random Matrix is :n");
/* For each of three rows */
28 for (i = 0; i < 3; i++) {
/* There are three columns.*/
30 for (j = 0; j < 3; j++) {
/* Assign a random matrix elements .*/
32 B[i][j] = rand_num (i * j);
printf("%dt", B[i][j]);
34 }
/* Print new line after completion of each row*/
36 printf("nn");
}
38 printf("nDot Product Matrix is :n");
/* For each of three rows */
40 for (i = 0; i < 3; i++) {
/* There are three columns.*/
42 for (j = 0; j < 3; j++) {
/* Elementwise dot product of matrices .*/
244 Array & Pointer
44 C[i][j] = A[i][j] * B[i][j];
printf("%dt", C[i][j]);
46 }
/* Print new line after completion of each row*/
48 printf("nn");
}
50 return 0;
}
✌
✆
✞
First Random Matrix is :
8 2 2
2 2 0
2 0 8
Second Random Matrix is :
8 8 8
8 2 2
8 2 8
Dot Product Matrix is :
64 16 16
16 4 0
16 0 64
✌
✆
The cross product (vector product) of two matrices is given by
~
C = ~
A × ~
B
✞
#include <stdio.h>
2
/* Random number generator between 0 to 10.*/
4 int newseed =10;
int seed (int a){
6 newseed =newseed+a;
return newseed;
8 }
int rand_num (int a) {
10 seed (a);
return (( newseed * 99991 + 12345) & 10);
12 }
14 int main () {
int i/* row*/;
16 int A[3]/* First Vector */,
B[3]/* Second Vector */,
18 C[3]/* Dot Vector */;
printf("First Random Vector is :n");
20 /* For each of three rows */
for (i = 0; i < 3; i++) {
22 /* Assign a random vector elements .*/
A[i] = rand_num (i);
24 printf("%dt", A[i]);
2.1. ARRAY 245
}
26 /* Print new line after completion of each row*/
printf("n");
28
printf("nSecond Random Vector is :n");
30 /* For each of three rows */
for (i = 0; i < 3; i++) {
32 /* Assign a random vector elements .*/
B[i] = rand_num (i);
34 printf("%dt", B[i]);
/* Print new line after completion of each row*/
36 }
printf("n");
38
printf("nCross Product Vector is :n");
40 /* For each of three rows */
for (i = 0; i < 3; i++) {
42 /* Elementwise cross product of matrices .*/
C[i] = pow(-1,2* i)* (A[(i+1) %3] * B[(i+2) %3] 
44 - B[(i+1) %3] * A[(i+2) %3]) ;
printf("%dt", C[i]);
46 }
/* Print new line after completion of each row*/
48 printf("nn");
50 return 0;
}
✌
✆
✞
First Random Vector is :
10 2 0
Second Random Vector is :
0 10 8
Cross Product Vector is :
16 -80 100
✌
✆
Arrays can be passed to a function as its parameter (argument) as shown in the example
given below:
✞
#include <stdio.h>
2 /*+- Array pointer with **
**| expandable size */
4 void init_array (int a[ ], int count) {
int i;
6 for (i = 0; i < count; i++)
a[i] = i * 10;
8 for (i = 0; i < count; i++)
printf("The a value is %d.n", a[i]);
10 }
12 int main (void ) {
int mydata [10];
246 Array & Pointer
14 init_array (mydata , 5);
return 0;
16 }
✌
✆
✞
The a value is 0.
The a value is 10.
The a value is 20.
The a value is 30.
The a value is 40.
✌
✆
For multidimensional array, there is no limit of dimension in C. Here, a four dimensional
matrix is represented by
✞
1 int myData [2][3][2][4]
✌
✆
A new dimension in array declaration is always grouped by curly braces. One dimensional
array has one curly braces, i.e. one row. In two dimensional array, there are two one
dimensional rows both separated by comma (,) operator. These two rows are enclosed by
another curly braces. In three dimensional systems of arrays, two 2-dimensional arrays
are placed one over another. In the following example, two, three and four dimensional
arrays are declared.
✞
1 #include <stdio.h>
3 int main () {
char a[2][2] = {
5 // cols
{1, 2}, // row
7 {5, 6} // row
};
9 char b[2][2][2] = {
{
11 // cols
{1, 2}, // row
13 {5, 6} // row
},
15 {// height
{4, 3},
17 {8, 9}
}
19 };
char c[2][2][2][2] = {
21 {
{
23 // cols
{1, 2}, // row
25 {5, 6} // row
},
27 {// height
{1, 2},
2.1. ARRAY 247
29 {5, 6}
}
31 },
{// time
33 {
{4, 1},
35 {7, 6}
},
37 {
{4, 4},
39 {9, 1}
}
41 }
};
43 int i, j, k, l;
printf("Elements of matrix a are n");
45 for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
47 printf("Element a[%d][%d] is : %dn",
i+1, j+1, a[i][j]);
49 }
}
51 printf("Elements of matrix b are n");
for (i = 0; i < 2; i++) {
53 for (j = 0; j < 2; j++) {
for (k = 0; k < 2; k++) {
55 printf("Element b[%d][%d][%d] is : %dn",
i+1, j+1, k+1, b[i][j][k]);
57 }
}
59 }
printf("Elements of matrix c are n");
61 for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
63 for (k = 0; k < 2; k++) {
for (l = 0; l < 2; l++) {
65 printf("Element c[%d][%d][%d][%d] is : %dn",
i+1, j+1, k+1, l+1, c[i][j][k][l]);
67 }
}
69 }
}
71 return 0;
}
✌
✆
It is an example of the two dimensional matrix in which total and average marks of each
student is calculated.
✞
#include <stdio.h>
2 #define STUDENT 3 // number of STUDENTS
#define SUBJECT 5 // number of SUBJECT
248 Array & Pointer
4
int main (void ) {
6 // marks of five stus
const float marks[STUDENT ][ SUBJECT ] = {
8 // subs ->
{9.9, 8.0, 8.3, 4.2, 6.0}, // stu row
10 {9.0, 7.0, 7.3, 2.0, 5.0}, // stu row
{9.6, 8.0, 8.8, 2.1, 5.5}, // stu row
12 };
int stu , sub;
14 float subtot , total;
printf("Student Marks (Max 50)n");
16
/* for each stu , sum marks for each sub */
18 total = 0;
for (stu = 0; stu < STUDENT; stu ++) {
20 for (sub = 0, subtot = 0; sub < SUBJECT; sub ++) {
subtot += *(*( marks + stu) + sub);
22 }
printf("%s %d %20.1fn", "Stu", stu + 1, subtot);
24 total += subtot; /* total for all stus */
}
26 printf("nThe student average is %.1f.nn",
total / STUDENT );
28
printf("Subject Average :n");
30 printf("Sub_1 Sub_2 Sub_3 Sub_4 Sub_5n");
32 /* for each sub , sum marks over stus */
for (sub = 0; sub < SUBJECT; sub ++) {
34 subtot = 0;
for (stu = 0; stu < STUDENT; stu ++) {
36 subtot += *(*( marks + stu) + sub);
}
38 printf("%5.1 f ", subtot / STUDENT );
}
40 printf("n");
return 0;
42 }
✌
✆
✞
Student Marks (Max 50)
Stu 1 36.4
Stu 2 30.3
Stu 3 34.0
The student average is 33.6.
Subject Average :
Sub_1 Sub _2 Sub_3 Sub_4 Sub_5
9.5 7.7 8.1 2.8 5.5
✌
✆
2.1. ARRAY 249
A multidimensional array may also be returned by a function, if function is used as a
pointer. An example for two dimensional array as a returned value of a function is given
below:
✞
#include <stdio.h>
2
int (* myF(int arr [3][3] , int n))[3] {
4 int i, j;
for (i = 0; i < 3; i++) {
6 for (j = 0; j < 3; j++) {
arr[i][j] = i + j;
8 }
}
10 return arr;
}
12
int main () {
14 int arr [3][3];
int (*q)[3] = myF(arr , 3);
16 int i, j;
for (i = 0; i < 3; i++) {
18 for (j = 0; j < 3; j++) {
printf(" %d", q[i][j]);
20 }
printf("n");
22 }
}
✌
✆
✞
0 1 2
1 2 3
2 3 4
✌
✆
2.1.3 Array of Strings
It is very simple to declara an array for integers, float, characters datatypes as they has
fixed size. But, in case of string, declaration of array is complex as size of string, being
stored in array like matrix form, is variable. For example, at a particular cell, we can store
string “me” or string “our”. Here, both words have different size. So, declaration of an
array for string needs special caution and care. Here, we shall discuss about the storing of
string data in an array, starting from one dimensional array to multi-dimensional array.
Suppose we have to store string “This”. We declare array like
✞
1 char myArr [];
✌
✆
Here, ‘[]’ controls the size of declared variable ‘myArr’ as dynamic and memory is allocated
and reallocated by compiler at run time according to the size of input string being stored.
Now, we store string “This” in this array, and appended by null terminator. The memory
data shall be looked like-
250 Array & Pointer
0×0012 0×0013 0×0014 0×0015 0×0016 0×0017 0×0018 0×0019
myArr
T h i s 0
Figure 2.5:
But what happens if we declare an fixed size one dimensional array as shown below:
✞
1 char myArr [10];
✌
✆
It means, above array may store only 10 characters including null terminator.
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 char myArr[]="This ";
printf("String is ’%s ’n",myArr);
7 return 0;
}
✌
✆
✞
String is ’This ’
✌
✆
If we try to store string of size more than 10 characters, data shall be overflow. From
figure 2.5, it is seen that each character of string ‘This’ is column of one row vector.
Therefore, when we declare a two dimensional array, one new parameter is required for
rows of the array alongwith other size of string parameter.
✞
1 char myArr[<rows >][< string size in each row >]
✌
✆
For example, an array
✞
1 char myArr [3][5]
✌
✆
tells us that, there are three rows and each row may store strings of five characters
including null terminator. Note that, the declaration parameter ‘[<string size in each
row >]’ is required only at the time of array declaration. When storing and retrieving of
strings, we just ignore it or just replace it by ‘[0]’ only.
2.1. ARRAY 251
0×0012 0×0013 0×0014 0×0015 0×0016
T h i s 0
i s 0
m y 0
0×0312 0×0313 0×0314 0×0315 0×0316
p e t 0
myArr[0]
myArr[1]
myArr[3]
Figure 2.6:
✞
1 #include <stdio.h>
#include <string.h>
3
int main () {
5 char myArr [4][5]={ "This ","is","my","pet"};
printf("String is ’%s ’n",myArr[0]) ;
7 printf("String is ’%s ’n",myArr[1]) ;
printf("String is ’%s ’n",myArr[2]) ;
9 printf("String is ’%s ’n",myArr[3]) ;
return 0;
11 }
✌
✆
✞
String is ’This ’
String is ’is ’
String is ’my ’
String is ’pet ’
✌
✆
Note that, a string variable is pointer of itself and points to address where data is stored.
So, use of ‘&’ symbol is optional. It also points to the address of first character of string,
so use of ‘[0]’ is also optional. So that, ‘myArr’ and ‘myArr[0]’ both return the string
‘This’.
✞
#include <stdio.h>
2 #include <string.h>
4 int main () {
char myArr [4][5]={ "This ","is","my","pet"};
6 printf("String is ’%s ’n",myArr);
printf("String is ’%s ’n",myArr[1]) ;
8 printf("String is ’%s ’n",myArr[2]) ;
printf("String is ’%s ’n",myArr[3]) ;
10 return 0;
}
✌
✆
✞
String is ’This ’
252 Array & Pointer
String is ’is ’
String is ’my ’
String is ’pet ’
✌
✆
We can also declare an array that is arranged in rows and columns and each column is of
fixed size for storing of strings.
✞
char myArr[<rows >][< cols >][< string size >]
✌
✆
0×0012 0×0013 0×0014 0×0015 0×0016
T h i s 0
0×0017 0×0018 0×0019 0×0020 0×0021
T h a t 0
i s 0 w a s 0
m y 0 m y 0
0×0312 0×0313 0×0314 0×0315 0×0316
p e t 0
0×0317 0×0318 0×0319 0×0320 0×0321
p e n 0
myArr[0][0]
myArr[1][0]
myArr[3][0]
myArr[0][1]
Figure 2.7:
See the example below:
✞
1 #include <stdio.h>
#include <string.h>
3
#define ROWS 4
5 #define COLS 2
#define STRING_SIZE 5
7
int main () {
9 char myArr[ROWS ][ COLS ][ STRING_SIZE ] = {
{"This ", "That "},
11 {"is", "was"},
{"my", "my"},
13 {"pet", "pen"}
};
15 int i;
printf("Data matrix is : n");
17 for (i = 0; i < ROWS ; i++) {
printf("%5s t %5sn", myArr[i][0], myArr[i][1]);
19 }
return 0;
21 }
✌
✆
✞
Data matrix is :
This That
is was
2.1. ARRAY 253
my my
pet pen
✌
✆
We can add new strings in this array by using strcpy function by indicating the address
of matrix cell.
✞
1 /*At fifth row , first column */
strcpy(arr [4][0] , "Hi");
3 /*At fifth row , second column*/
strcpy(arr [4][1] , "His");
✌
✆
While we use scanf function to add user’s input from input stream, we should exactly
known to the address of memory byte where data is to be stored.
✞
#include <stdio.h>
2 #include <string.h>
4 #define ROWS 5
#define COLS 2
6 #define STRING_SIZE 5
8 int main () {
char myArr[ROWS ][ COLS ][ STRING_SIZE ] = {
10 {"This ", "That "},
{"is", "was"},
12 {"my", "my"},
{"pet", "pen"}
14 };
int i;
16 printf("Enter data for 5th row 1st column :");
scanf("%s", myArr [4][0]) ;
18 printf("Enter data for 5th row 2nd column :");
scanf("%s", &myArr [4][1][0]) ;/* last [0] is optional */
20 printf("Data matrix is : n");
for (i = 0; i < ROWS ; i++) {
22 printf("%5s t %5sn", myArr[i][0], myArr[i][1]);
}
24 return 0;
}
✌
✆
✞
Enter data for 5th row 1st column :hi
Enter data for 5th row 2nd column :his
Data matrix is :
This That
is was
my my
pet pen
hi his
✌
✆
We can also declare a static multidimensional array by using pointers. It is declared as
254 Array & Pointer
✞
char * myArr[<rows >]
✌
✆
Data should be assigned at the time of declaration. Pointer character ‘*’ is responsible
for dynamic allocation of memory of suitable size so that assigned data is stored in the
array. See the example below:
✞
1 #include <stdio.h>
3 int main () {
/* Static array declaration */
5 char * myArr[2] = {"This ", "is"};
printf("First row string is : %sn", myArr[0]) ;
7 printf("Second row string is : %s", myArr[1]) ;
return 0;
9 }
✌
✆
✞
First row string is : This
Second row string is : is
✌
✆
0×0012 0×0013 0×0014 0×0015 0×0016
T h i s 0
0×0112 0×0113 0×0114 0×0115 0×0116
i s 0
myArr[0]
myArr[1]
Here, two strings have static storage prior to the program startup. In the initializer, the
arrays are converted to pointers to char and the words array is initialized with the pointer
values. It can not be modified during the program run. It has its own advantages as we
can access to character of string by using pointers.
✞
#include <stdio.h>
2
int main () {
4 char * myArr[3] = {"This ", "is"};
printf("First row string is : %sn", myArr[0]) ;
6 printf("Same from index 1 is : %s n", (myArr [0]+1));
return 0;
8 }
✌
✆
✞
First row string is : This
First row string from index 1 is : his
✌
✆
Here, ‘myArr[0]+1’ means pointer points to the first row string at index ‘0’ and pointer
position is changed by one character position rather than next row.
2.1. ARRAY 255
0×0012 0×0013 0×0014 0×0015 0×0016
T h i s 0
0×0112 0×0113 0×0114 0×0115 0×0116
i s 0
myArr[0]+1
myArr[1]
Using pointer, we can access whole string or its part of string. For example, ‘*myArry’
is the same as myArry[0]. ‘(*myArry)[0]’ is the same as **myArry, which is the first
character of the string and not the address of the string.
✞
#include <stdio.h>
2
int main () {
4 char * myArr[2] = {"This ", "Home "};
printf("For ’This ’ : %sn", myArr [0]) ;
6 printf("For ’Home ’ : %sn", myArr [1]) ;
/* Address of ’This ’ pointed by * myArr and*
8 *it points to address of character ’T’ */
printf("For ’This ’ : %sn", *myArr);
10 /* Dereference to pointer that is pointing *
*to address where string ’This ’ is stored. *
12 *Pointer points to location of character ’T ’.*/
printf("For ’T’ : %c n", ** myArr);
14 /* same as above*/
printf("For ’T’ : %c n", (* myArr)[0]) ;
16 /* Dereference to pointer that is pointing *
*to address where string ’This ’ is stored.*
18 *Pointer in incremented by one , and now , *
*it points to location of character ’h ’. */
20 printf("For ’h’ : %c n", (* myArr)[1]) ;
/* same as above*/
22 printf("For ’h’ : %c n", *(* myArr +1));
return 0;
24 }
✌
✆
✞
For ’This ’ : This
For ’Home ’ : Home
For ’This ’ : This
For ’T’ : T
For ’T’ : T
For ’h’ : h
For ’h’ : h
✌
✆
2.1.4 Array in Function
In functions arguments are passed to it as value unless the function needs alter the
argument. If function needs update the argument, argument should be passed to function
as its argument. Arrays can also passed to functions as pointers. If an array is passed to
256 Array & Pointer
the function, function would have to allocate enough space to hold a copy of the original
array and then copy all the data from the original array to the new array. It is much
quicker to pass the address of the array rather than array itself and have the function
work with the original data. Prototype for the passing of an array to the function is
✞
1 int sum(int arr[ ])
/*Or*/
3 int sum(int *arr)
✌
✆
sum()
i0 i1 i2 i3 i4
3 6 9 12 15
anArray
S
Figure 2.8: Passing of address of array to sum() function. Array is pointed by the
pointer/variable ‘anArray’.
In C, array parameters are always treated as pointers. C compilers do not check the
size of the array passed to the function hence for good programming, the function should
know the limits of actions on the array. This is why a new parameter of array size as ‘n’
is passed to the function as
✞
1 int sum(int arr[ ], int n)
✌
✆
sum()
for(i=0; i<n; i++){
S += anArray[i];
}
i0 i1 i2 i3 i4
3 6 9 12 15
anArray
n
S
Figure 2.9: Passing of address of array as well as element size of the array to sum()
function. Array is pointed by the pointer/variable ‘anArray’.
Because the name of an array is the address of the first element, an actual argument of
an array name requires that the matching formal argument be a pointer. In this context
int arr[ ] to mean the same as the int * arr. First bracket in the multidimensional array
may be empty or not but other brackets should contains the valid integers for the size of
the array dimension. For example
2.1. ARRAY 257
✞
1 int sum(int arr[ ][ ], int rows ); // faulty declaration
✌
✆
is a faulty declaration. Recall that the compiler converts array notation to pointer no-
tation. It means, that arr[1] will become arr+1. For the compiler to evaluate this, it
needs to know the size of object to which ‘arr’ points. The declaration
✞
1 int sum2 (int arr[ ][4], int rows ); // valid declaration
✌
✆
says that ‘arr’ points to an array of four integers, so ‘arr+1’ means “add 16 bytes to the
address”. If first bracket contains a number then it will be ignored.
✞
1 int sum2 (int ar [3][4] , int rows ); // valid declaration , 3 ignored
✌
✆
✞
1 #include <stdio.h>
#define ROWS 3
3 #define COLS 4
int sum(int rows , int cols , int ar[rows ][ cols ]);
5
int main (void ) {
7 int i,j;
int varr [ROWS ][ COLS ];
9 for (i = 0; i < ROWS ; i++)
for (j = 0; j < COLS ; j++)
11 varr [i][j] = i * j + j;
printf("3x4 Array n");
13 printf("Sum of all elements = %dn",
sum(ROWS , COLS , varr ));
15 return 0;
}
17 int sum(int rows , int cols , int ar[rows ][ cols ]) {
int r;
19 int c;
int tot = 0;
21 for (r = 0; r < rows ; r++)
for (c = 0; c < cols ; c++)
23 tot += ar[r][c];
return tot;
25 }
✌
✆
✞
3x4 Array
Sum of all elements = 36
✌
✆
An array can passed to a function by using function prototype as shown in syntax given
below:
✞
#include <stdio.h>
2
void PrintIt (char Str[ ]) {
4 printf("%sn", Str);
258 Array & Pointer
}
6
int main () {
8 char label[ ] = "Allora Caves.";
PrintIt (label);
10 return 0;
}
✌
✆
The output is
✞
Allora Caves.
✌
✆
Function PrintIt() expects a character array. When an array is declared as the
parameter to a function, it really gets a pointer. Arrays are always automatically passed
by reference. Similarly a pointer can also pass to a function as an array or as a pointer.
✞
1 #include <stdio.h>
3 void PrintIt (char Str[ ]) {
printf("%sn", Str);
5 }
7 int main () {
char * label = "Allora Caves.";
9 PrintIt (label);
return 0;
11 }
✌
✆
The output is
✞
Allora Caves.
✌
✆
✞
1 #include <stdio.h>
3 void PrintIt (char *Str) {
printf("%sn", Str);
5 }
7 int main () {
char * label = "Allora Caves.";
9 PrintIt (label);
return 0;
11 }
✌
✆
The output is
✞
Allora Caves.
✌
✆
Unfortunately, (in C and C++) the length of the array cannot be obtained from an
array passed to a function at run time, because the size of an array is not stored anywhere.
The compiler always replaces sizeof () with a constant. See the following example
2.1. ARRAY 259
✞
1 #include <stdio.h>
#include <string.h>
3
#define NUM_ELEM (x) (sizeof (x) / sizeof (*(x)))
5
int sum(int input_array [ ]) {
7 int sum_so_far = 0;
int i;
9 /* Would NOT Work ; input_array was*
*not defined in this function . */
11 for (i = 0; i < NUM_ELEM (input_array ); i++){
sum_so_far += input_array [i];
13 };
return ( sum_so_far );
15 }
17 int main (int argc , char *argv [ ]) {
int left_array [ ] = {1, 2, 3};
19 int right_array [ ] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
int the_sum = sum(left_array );
21 printf("the sum of left_array is: %d n", the_sum );
the_sum = sum(right_array );
23 printf("the sum of right_array is: %d n", the_sum );
25 return 0;
}
✌
✆
When this example is run, it gives output as shown below
✞
the sum of left _array is 1
the sum of right_array is 10
✌
✆
whatever the values are passed as argument in the sum function. This ‘sum()’ routine
needs to handle more than just one constant length of an array. There are some common
ways to work around this fact:
1. Write the function as required, for each array parameter and parameter “length”
which has type “size t”. We can use sizeof () at the point where this function is
called.
2. Use of a null-terminated string to mark the end of the array if array is string. Arrays
representing to numbers does not need the null-terminating string to mark of the
end of array. Instead it, number arrays are passed to the function along with its
element size.
3. Pass the arrays as well as array length parameter to the function. We can pass
the pointer-to-array if required. Evaluate the data as per rules set by function
statements or expressions.
Using these facts, above example is now modified as given below.
260 Array & Pointer
✞
#include <stdio.h>
2
#define NUM_ELEM (x) (sizeof (x) / sizeof (*(x)))
4
int mySum(int array[ ], size_t length) {
6 int sum = 0;
int i;
8 for (i = 0; i < length; i++) {
sum += array[i];
10 };
return ( sum);
12 }
14 int main (int argc , char *argv [ ]) {
int sum;
16 int i_array [ ] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
/* Works here , because the size of right_array *
18 *is passed to the sum function as argument */
sum = mySum(i_array , NUM_ELEM (i_array ));
20 printf("The sum is : %d.n", sum);
22 return 0;
}
✌
✆
Output of above example is
✞
the sum is : 55
✌
✆
The same method of passing an array to a function and getting sum of all array element
is also possible with other number datatypes. Above example is suitable modified for array
contains floating type numbers.
✞
1 #include <stdio.h>
3 #define NUM_ELEM (x) (sizeof (x) / sizeof (*(x)))
5 /* Function returns floating data . So mySum()*
*should be declared as floating data type . */
7 float mySum(float in_array [ ], size_t length) {
float sum = 0;
9 int i;
for (i = 0; i < length; i++) {
11 sum += in_array [i];
};
13 return ( sum);
}
15
int main (int argc , char *argv [ ]) {
17 float sum;
float array[ ] = {10.10 , 50.50 , 4.57, 1.21};
19 sum = mySum(array , NUM_ELEM (array));
2.1. ARRAY 261
printf("The sum is : %fn", sum);
21 return 0;
}
✌
✆
✞
The sum is : 66.379997
✌
✆
It’s worth mentioning that sizeof () operator has two variations: sizeof (type) and sizeof (<expression>).
An example using sizeof () function to a pointer is shown below.
✞
1 #include <stdio.h>
#include <string.h>
3
int main (int argc , char *argv [ ]) {
5 char buffer [10];
if (argc < 2) {
7 fprintf (stderr , "USAGE: %s stringn", argv [0]) ;
return 1;
9 }
strncpy (buffer , argv [1], sizeof ( buffer));
11 buffer[sizeof (buffer) - 1] = ’0 ’;
return 0;
13 }
✌
✆
Output of the script is
✞
USAGE: executable .exe string
✌
✆
2.1.5 String As Array
C has no built in string handling facilities. Consequently, string is defined as array of
characters. C allows a character array to be represented by a character string rather than
a list of characters, with the null terminating character, automatically added to the end.
Example of string array is shown below.
✞
1 char s[ ] = {’A’, ’p’, ’p’, ’l’, ’e’, ’s’, ’0’};
✌
✆
A p p l e s 0
s
Figure 2.10: Array of characters constructing word ‘Apples’ is stored in memory and
pointed by variable ‘s’.
Normally size of string array is controlled at initialisation. An string array can store only
the number of characters upto its length. Rest of the characters are ignored. In following
example only ten characters will be stored in the string array ‘mystr’.
262 Array & Pointer
✞
1 char mystr [10] = "Apple is red.";
✌
✆
It is convenient to let the compiler determine the array size. If one omits the size in an
initializing declaration, the compiler determines the size for supplied string. In following
example, compiler set the string length of thirteen characters.
✞
1 char mystr[ ] = "Apple is red.";
✌
✆
A pointer notation may aslo be set up to represent a string. In pointer notation, above
example will be look like
✞
1 const char *ptrstr = "Delhi";
✌
✆
D e l h i 0
ptrstr
Figure 2.11: Character array ‘Delhi’ stored in memory. ‘ptrstr’ points to the character
array ‘Delhi’.
Both declarations amount to saying that ‘ptrstr’ is a pointer to the indicated string.
Strings as array or pointer, are same but only the pointer version can use the increment
operator while array version does not support increment operator. To create an extra long
string, string is splitted into multiple sections, by closing the first section with a quote,
and recommencing the string on the next line (also starting and ending in a quote):
✞
1 char string[ ] = "This is a very , very long "
"string that requires two lines.";
✌
✆
See the example below
✞
#include <stdio.h>
2
int main () {
4 char ch;
char string[ ] = "Two lines "
6 "string.";
int i = 0;
8 while (string[i] != ’0’) {
ch = string[i];
10 printf("%c.", ch);
i++;
12 }
return (0);
14 }
✌
✆
2.1. ARRAY 263
✞
T.w.o. .l.i.n.e.s. .s.t.r.i.n.g...
✌
✆
When an array is assigned the characters to get the string, there must be a terminating
null character. Otherwise there shall be garbage output. For example following syntax
has no terminating null character. It is not in standard format.
✞
1 char a[10];
a[0]= ’a’;
3 a[1]= ’r’;
a[2]= ’u’;
✌
✆
This format should be like
✞
char a[10];
2 a[0]= ’a’;
a[1]= ’r’;
4 a[2]= ’u’;
a[3]= ’0’;
✌
✆
See following two examples, in which string is terminating without and with null character.
First example gives garbage output (see below).
✞
1 #include <stdio.h>
3 int main () {
char a[10];
5 a[0]= ’a’;
a[1]= ’r’;
7 a[2]= ’u’;
printf("%s",a);
9 return 0;
}
✌
✆
✞
<garbage output >
✌
✆
In this second example, string is terminated with null character. This example gives
output what we required.
✞
1 #include <stdio.h>
3 int main () {
char a[10];
5 a[0]= ’a’;
a[1]= ’r’;
7 a[2]= ’u’;
a[3]= ’0’;
9 printf("%s",a);
return 0;
11 }
✌
✆
264 Array & Pointer
✞
aru
✌
✆
Size of static array should be larger by one to the original data size being stored in the
array. This extra byte is for NULL terminator, i.e. 0. To store one byte data, array size
should be larger than one. For storing n byte data, array size should be > n. Here two
examples are given. In first example, array size is equal to the data size and in second
example, array size is larger than data size by one. This extra one byte is used to store
null terminating character.
✞
1 #include <stdio.h>
#include <stdlib.h>
3
int main (void ) {
5 /* Deficient static array *
* size declared as char c.*/
7 char c[1];
printf("Enter char ’e’ : ");
9 gets (c);
if (( strcmp(c, "e") == 0))
11 printf("%sn", c);
return 0;
13 }
✌
✆
On compilation, it gives error while following example gives desired output.
✞
1 #include <stdio.h>
#include <stdlib.h>
3
int main (void ) {
5 /* Suficient static array *
* size declared as char c.*/
7 char c[2];
printf("Enter char ’e’ : ");
9 gets (c);
if (( strcmp(c, "e") == 0))
11 printf("%sn", c);
return 0;
13 }
✌
✆
✞
e
✌
✆
In first example, array ‘c’ can store only character ‘c’. There is no extra space to store
null terminating character. It makes that array ‘c’ does not hold string in proper format.
In second example, array ‘c’ can store one character as well as null terminating character.
By this way it holds string in proper format.
2.1.6 Size of Array
C features two kinds of arrays: static (compile-time, fixed size) and dynamic (allocated
at run-time). The length of a dynamic array cannot be acquired from the array itself -
2.1. ARRAY 265
its length must be stored elsewhere. The size of static array is computed as
✞
1 int length = sizeof(<array name >) / sizeof(<array element >);
✌
✆
Preprocessor ways for array length is defined as
✞
1 #define ARRAY_LENGTH (A) (sizeof(A) / sizeof(A[0]) )
✌
✆
i0 i1 i2 i3 i4
3 6 9 12 15
anArray
n
Figure 2.12: Size of ‘anArray’ is the number of elements pointed by ‘anArray’. Here
remember that array is of integer type, hence each element shown in this figure needed
4 bytes long memory space. There are 5 elements in this array, so size of ‘anArray’ is 5
(n = 5) and these elements needed 5 × 4 = 20 bytes long memory space.
Array becomes pointer when it is passed as a parameter to a function. Thus, the length of
an array parameter may not require directly but a dedicated length parameter is required
and should be passed to the function. See the following example is given string array
‘fruit’ is declared with static size of 2 elements in each row while each row is pointed by
‘fruit’ pointer itself. Hence the element size is fixed so, there is no need to calculate the
length size of array. But in this example, length is computed by using above syntax.
✞
1 #include <stdio.h>
3 int main (){
const char *fruit[2] = { "apples", "oranges" };
5
/* Length of the array by dividing *
7 *the size of all elements by the*
*size of the first element. */
9
int length = sizeof(fruit) / sizeof(fruit[0]) ;
11
printf("%dn", length);
13
return 0;
15 }
✌
✆
✞
2
✌
✆
In above example, length of the array is obtained by dividing the size of all elements
(found with sizeof (fruit)) by the size of the first element. Note that since the array
elements are pointers to null-terminated character arrays, the size of the first element is
actually the size of the pointer type - not the length of the string. This size, regardless
of the type being pointed to, is 8 bytes, 4 bytes, or 2 bytes on 64-bit, 32-bit, or 16-bit
266 Array & Pointer
platforms respectively. Pointer can be used for variable size array as shown in example
below.
✞
1 #include <stdio.h>
/* Variable size array.*/
3 char *name ;
int main () {
5 name ="My School!!";
int i=0;
7 while(name [i] !=’0 ’){
printf("%cn",name [i]);
9 i++;
}
11 return 0;
}
✌
✆
✞
M
y
S
c
h
o
o
l
!
!
✌
✆
2.1.7 Vector & Matrix
Vector is a one dimensional array or a matrix having one rows and multiple columns. A
vector is represented by A = [1, 2, 3, 5]. A matrix is vertical arrangement of vectors. Vec-
tors are one dimensional arrangement of coefficients of variables of an algebraic equation.
Let an algebraicequation ax + by = k, that is written as
ax + by − k = 0
Now, vector u for this algebraic equation is given by
u = [a, b, −k]
If there is a set of two algebraic equations,
ax + by − k = 0
cx + dy − l = 0
Then two vectors of these two algebraic equations are u and v respectively as
u = [a, b, −k]; v = [c, d, −l]
2.1. ARRAY 267
The matrix arrangement like AX = B is

a b −k
c d −l



x
y
1

 =

0
0

Here, matrix A is row arrangement of two vectors u and v. Similarly, for example, vectors
A = [1, 2, 3, 5] and B = [5, 4, 3, 2] form a matrix when these vectors are arranged vertically.
C =
c programming
c programming
c programming
1 2 3 5
5 4 3 2
c programming
c programming
c programming
Here, C is a 2 × 4 matrix. A one dimensional vector is defined in C like
✞
#include stdio.h
2
int main (void ) {
4 int A[5];
int i;
6 for (i = 1; i  5; i++) {
A[i] = i;
8 }
for (i = 1; i  5; i++) {
10 printf(%dt, A[i]);
}
12 return 0;
}
✌
✆
✞
1 2 3 4
✌
✆
A matrix is defined in C like
✞
1 #include stdio.h
3 int main (void ) {
int A [2][5];
5 int i, j;
for (i = 0; i  2; i++) {
7 for (j = 0; j  4; j++) {
A[i][j] = i + j;
9 }
}
11 for (i = 0; i  2; i++) {
for (j = 0; j  4; j++) {
13 printf(%dt, A[i][j]);
}
15 printf(nn, A[i][j]);
}
17 return 0;
}
✌
✆
268 Array  Pointer
✞
0 1 2 3
1 2 3 4
✌
✆
In C, arrays, vectors and matrices are defined in same ways.
2.1.8 Sparse Matrix
A sparse matrix is one which have majority number of zeros along rows and columns. For
example a sparce matrix is
S =






0 0 0 0 0
0 1 2 0 1
0 2 1 0 2
0 0 0 0 0
0 1 2 0 1






C program for sparse matrix is given below:
✞
1 #include stdio.h
#include time .h
3
int main () {
5 time_t t1 , t2;
t1 = time (NULL );
7 static int array [10][10];
int i, j, m = 5, n = 5;
9 int counter = 0;
for (i = 0; i  m; ++i) {
11 for (j = n; j  0; --j) {
t2 = time (NULL );
13 array[i][j] = (i * j + t2) % (t1 % 5 + 1);
if (array[i][j] == 0) {
15 ++ counter ;
}
17 }
}
19 printf(Matrix is : n);
for (i = 0; i  m; ++i) {
21 for (j = 0; j  n; ++j) {
printf(%dt, array[i][j]);
23 }
printf(n);
25 }
if (counter  ((m * n) / 2)) {
27 printf(Matrix is sparse matrix n);
} else {
29 printf(Matrix is not a sparse matrix n);
}
31 printf(There are %d number of zeros.n, counter );
2.2. POINTER 269
return 0;
33 }
✌
✆
Above proram uses the current CPU time so each time when program is run, a different
matrix is generated. The matrix generated may be a sparse matrix or not. The one run
state matrix generated by above program is given below, which is not a sparse matrix.
✞
Matrix is :
0 4 4 4 4
0 0 1 2 3
0 1 3 0 2
0 2 0 3 1
0 3 2 1 0
Matrix is not a sparse matrix
There are 4 number of zeros.
✌
✆
2.2 Pointer
A pointer is a simple variable that stores the address (the location in memory) of a value
in memory rather than storing data itself. A variable is said to be declared as a pointer
if it prefixed with an asterisk symbol. A variable name with prefixed ampersand ()
defines the address of itself. A pointer with prefixed asterisk, except declaration, refers to
the value of the variable whose address is pointed-by the pointer. The address to which
pointer points is called pointee address.
0×50 0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59
0×0504
int *i; pointer address
pointee address
There are two valid pointer operations, (i) comparison of two pointers and (ii) addi-
tion or subtraction. Address of memory cell and value stored at that memory cell both
constitute different meanings. Memory is array of many bits which is capable of storing
values either binary 1 or binary 0. This size of memory has no meaning as it can not store
large numeric value, so multiple bits are grouped to form bytes (one byte has 8 bits). Too
store an integer, 4 bytes (32 bits) are grouped together. See the following constitution of
memory cells.
0×1001 0×1005 0×1009 0×1013
Value at memory cell
Address of memory cell
00000000 00000000 00000011 11101001
270 Array  Pointer
In which, each memory cell or memory location is identified by its address and it
contains a value. See an example given below. Read program line-by-line alongwith
comments carefully.
✞
#include stdio.h
2 int main (){
/*i points to memory location where 10 is stored. */
4 int i=10;
6 /* Pointer j points to a random address */
int *j;
8
/* Now j points to same address as i is pointing . */
10 j=i; // i and j points to same address.
12 /*j stored value at its address.*/
*j=20;
14
/*As i and j points to same memory location *
16 *( addresses ) therefore , values of i and j *
*are equal. So , i = 20. */
18 printf(%d,i); //i has same value as j;
return 0;
20 }
✌
✆
✞
20
✌
✆
An array name is also the address of the first element of the array. That is, if ‘arr’ is an
array, then
✞
1 arr == arr [0]; // name of array is the
// address of the first element
✌
✆
Both ‘arr’ and ‘arr[0]’ represent the memory address of first element of the array. It is
also called the reference of the array ‘arr’. A pointer can points to any element of the
array, if the pointer is assigned address of that element. In the following example, pointer
‘x’ points to the address of first element of the array ‘i’.
✞
#include stdio.h
2
int main () {
4 int i[5] = {10, 20, 30, 40, 50};
int *x = i[0]; /* Points to first element.*/
6 printf(%d, *x);
return 0;
8 }
✌
✆
2.2. POINTER 271
0×10
10
0×11
20
0×12
30
0×13
40
0×14
50
i[ ]
x
The output of above program shall be
✞
10
✌
✆
If above example is modified as given below, then the pointer ‘x’ points to the 3rd
element of the array ‘i’.
✞
1 #include stdio.h
3 int main () {
int i[5] = {10, 20, 30, 40, 50};
5 int *x = i[2]; /* Points to third element.*/
printf(%d, *x);
7 return 0;
}
✌
✆
0×0
10
0×1
20
0×2
30
0×3
40
0×4
50
i[ ]
x
The output of above program shall be
✞
30
✌
✆
If an integer is pointed by a pointer-to-char variable, then this variable can points to
the address of each byte of the integer variable (integer variable is 4 bytes long).
✞
1 #include stdio.h
3 int main () {
/* 1000 D = 1111101001 B*/
5 int i = 1001;
/* Pointer casting from integer to character .*/
7 char *x = (char *) i;
/* Little endian is x[0]=11101001 B*
9 *Big endian is x[1]=00000011 B*
*Big endian x[2]= x[3]=00000000 B*/
11 /* Print little endian x[0]*/
printf(%d, (int) x[0]) ;
13 return 0;
}
✌
✆
272 Array  Pointer
x[3] x[2] x[1] x[0]
i:
x
00000000 00000000 00000011 11101001
Output of above program is
✞
-23
✌
✆
✞
1 #include stdio.h
3 int main () {
/* 1000 D = 1111101001 B*/
5 int i = 1001;
/* Pointer casting from integer to character .*/
7 char *x = (char *) i;
/* Little endian is x[0]=11101001 B*
9 *Big endian is x[1]=00000011 B*
*Big endian x[2]= x[3]=00000000 B*/
11 /* Print big endian x[1]*/
printf(%d, (int) x[1]) ;
13 return 0;
}
✌
✆
x[3] x[2] x[1] x[0]
i:
x
00000000 00000000 00000011 11101001
Output of above program is
✞
3
✌
✆
Though, the pointers allow increment and decrement operations but they are not
preferred over indexed arrays when there is requirement of random access. In indexed
arrays, fifth element can be accessed by myArr[4]. But in pointer array, we have to
first reach at the address of fifth element by using pointer increments or decrements
operations and then dereference the pointer. So, pointer requires extra coding to reach
at desire destination.
Identification of Pointer Type We know that, in C, a variable is declared as
✞
1 datatype  var name ;
✌
✆
There are three main form of variable object declarations. (i) normal variables, (ii) arrays
and (iii) functions. Their prototypes are respectively
2.2. POINTER 273
✞
1 int i; // normal variable
int k[10]; // array variable
3 int f(); // function variable
✌
✆
In above three declarations, priority is observed to identify the type of variable. In first
case, variable ‘i’ is normal integer type variable which stores integer values. It means
where ever it stores a value, it will be an integer. Priority of variable literal is lower
than square brackets or parentheses. A variable is followed by square brackets, then it is
treated as an array. Similarly, if a variable is followed by parentheses, then it is treated
as function. Now, the question is, how we identify the nature of variable when asterisk is
prefixed to variable literals to make it pointer variable as shown below:
✞
1 int *i;
int *k[10];
3 int *f();
✌
✆
Its answer is again priority listing. The priority of pointer symbol (asterisk) is less than
array symbol or parentheses. Hence first declaration is pointer to integer. In second
declaration, priority of variable ‘k’ goes with array symbol and asterisk makes it pointers.
Hence, it will be pronounce as “array k of pointers-to-integers”. Note that, datatype only
told about the type of data pointed by the pointers, not about the type of pointer itself.
Similarly, third declaration is “function which returns a pointer pointing-to-an-integer
value”. Remember, array always stores values and function always returns a value. Now,
parentheses are used to change the priority of asterisk like
✞
1 int *i;
int (*k)[10];
3 int (*f)();
✌
✆
The first declaration has no change. It is pointer to an integer. In second declaration,
priority of asterisk goes with ‘k’. Hence it is pronounce as “pointer ‘k’ to an array (due
to presence of square bracket) of integers (array stores integer type values)”. Similarly
third declaration is pronounced as “pointer ‘f’ points to a function (due to presence of
parentheses) which returns an integer value”. So, be careful while using pointers with
specific priorities. There is not change in the priority if data type is changed. For example,
only stored value at pointee address is changed to real (double data type) from integer if
above declaration is modified as
✞
1 double *i;
double (*k)[10];
3 double (*f)();
✌
✆
2.2.1 Declaring pointers
When a variable name is preceded by asterisk symbol during its declaration, it is called
pointer variable. In the following variable declarations:
274 Array  Pointer
✞
1 long *var1 , var2 ; // Declaration of pointer
int **p3; // Declaration of pointer to a pointer
✌
✆
In line 1, ‘var1’ is declared as a pointer variable to a long data type, i.e. data stored
at the pointed-to address will be long data type. And ‘var2’ is declared as a long data
type variable and it is not a pointer to a long data type as it is not preceded by asterisk
symbol. In line 2, ‘p3’ is declared as a pointer to a pointer to an int data type. Data
types which precedes to a pointer variable during pointer declaration specify about the
data read or write at the address pointed-to by the pointer variable. If data type is char
type, then will be read at the address location in group of one byte. If data type is int
type, then data will be read at the address location in group of four bytes and so on.
Remember that uninitialized pointers results in dangling or wild pointers, therefore each
pointer declared must be initialized as NULL pointer.
✞
int *p = NULL ; // Declaration  initialization of pointer
✌
✆
It is also safe to initialized a pointer to NULL when its allocated memory is freed by
using free() function.
✞
1 int *p = NULL ; // Declaration  initialization of pointer
p=malloc (10) ; // Allocate memory space
3 free (p); // Free memory space allocated to pointer
p=NULL ; // Initialize NULL to pointers
✌
✆
Pointer types are often used as parameters to function calls.
✞
int MyFunction ( struct MyStruct *pStruct );
✌
✆
In the above syntax, it is explained that how to declare a function which uses a pointer as
an argument. Since C passes function arguments by value, in order to allow a function to
modify a value from the calling routine, a pointer to the value must be passed. Pointer-
to-Structure is also used as function arguments even when nothing in the struct will be
modified in the function. This is done to avoid copying the complete contents of the
structure onto the stack. A simple example is
✞
1 #include stdio.h
#include time .h
3 void getSeconds (unsigned long *par);
5 int main () {
unsigned long sec;
7 getSeconds ( sec);
printf(No. of seconds since 01 Jan 1970: %ldn, sec);
9 return 0;
}
11
void getSeconds (unsigned long *par) {
13 *par = time (NULL );
return;
15 }
✌
✆
2.2. POINTER 275
✞
No. of seconds since 01 Jan 1970: 1420616845
✌
✆
Solved Problem 2.1 See the following memory arrangement. A pointer variable is declared
and assigned address as given in below code lines. What will be the print output?
Solution The memory arrangement is :
0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59
00000000 00000000 10010101 10110101 10110101 11111111 10011101 10101101 10010001
✞
1 char *ptr =0 x53;
printf(%d, *ptr);
✌
✆
Here, pointer is declared as char type, hence it shall read data stored at address 0×53 in
a group of one byte (byte group size is equal to the size of char data type).
0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59
00000000 00000000 10010101 10110101 10110101 11111111 10011101 10101101 10010001
So, the printf function will give output in decimal form which is equal to the value
stored at the address of 0×53. From the memory arrangement, value is 100101012, that
is decimal equivalent to 14910.
Solved Problem 2.2 See the following memory arrangement. A pointer variable is declared
and assigned address as given in below code lines. What will be the print output?
Solution The memory arrangement is :
0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59
00000000 00000000 10010101 10110101 10110101 11111111 10011101 10101101 10010001
✞
short *ptr =0 x53;
2 printf(%d, *ptr);
✌
✆
Here, pointer is declared as short type, hence it shall read data stored at address 0×53 in
a group of two bytes (bytes group size is equal to the size of short data type).
0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59
00000000 00000000 10010101 10110101 10110101 11111111 10011101 10101101 10010001
So, the printf function will give output in decimal form which is equal to the value
stored in two consecutive bytes whose first byte is at the address of 0×53. From the
memory arrangement, value is 10010101101101012, that is decimal equivalent to 3832510.
276 Array  Pointer
Solved Problem 2.3 See the following memory arrangement. A pointer variable is declared
and assigned address as given in below code lines. What will be the print output?
Solution The memory arrangement is :
0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59
00000000 00000000 10010101 10110101 10110101 11111111 10011101 10101101 10010001
✞
short *ptr =0 x53;
2 printf(%d, *( ptr ++));
✌
✆
Here, pointer is declared as short type, hence it will point to address of data stored from
address 0×53 onward in a group of two bytes (bytes group size is equal to the size of short
data type). The increment of pointer ‘ptr++’ will increase the address pointed by the
pointer variable ‘ptr’ by two bytes (equal to the size of declaration data type, here it is
short).
0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59
00000000 00000000 10010101 10110101 10110101 11111111 10011101 10101101 10010001
Thus the address pointed by the pointer variable ‘ptr’ is 0×55. So, the printf function
will give output in decimal form which is equal to the value stored in two consecutive
bytes whose first byte is at the address of 0×55. From the memory arrangement, value is
10110101111111112, that is decimal equivalent to 4659110.
Assigning values to pointers
A pointer variable points to an address. So, its value is always an address of other
variable. The address of a variable is accessed by using ‘address of’ operator, represented
by symobl ‘’. The standard procedure of assigning value to a pointer variable is shown
in the following code snippets.
✞
/*An interger variable that have *
2 *null value stored in memory. */
int myInt;
4 /* Pointer that addresses to a integer value.*/
int *ptr;
6 /* Address to the pointer where *
*myInt value is stores in memory.*/
8 ptr = myInt;
✌
✆
Here, ‘ptr’ will now reference to ‘myInt’. Pointers can also be assigned to dynamically
allocated memory. See the following example.
✞
#include stdio.h
2 int j, k;
int *ptr;
4
2.2. POINTER 277
int main (void ) {
6 j = 1;
k = 2;
8 ptr = k;
printf(j has value %d and stored at %pn, j, (void *) j);
10 printf(k has value %d and stored at %pn, k, (void *) k);
printf(‘ptr’ = %p and stored at %pn, ptr , (void *) ptr);
12 printf(Value of the integer pointed -by ‘ptr’ is %dn, *ptr);
return 0;
14 }
✌
✆
✞
j has value 1 and stored at 0x403100
k has value 2 and stored at 0x403120
‘ptr ’ has value 0x403120 and stored at 0x403110
Value of the integer pointed -by ‘ptr ’ is 2
✌
✆
2
0×50
3
0×51
4
0×52
5
0×53
6
0×54
7
0×55
8
0×56
int *ptr = k
k
k
A pointer is created by using asterisk (*) as shown in the first line of the below code.
Method of value assignment to the variable is shown in second line of the following code.
✞
int *j;
2 j = 5;/* Valid  good practice .*/
✌
✆
This type of assignment updated value stored at the address of pointer variable itself. In
above type of pointer assignment, pointer now points to the memory whose address is
0×05. See the example
✞
#include stdio.h
2
int main () {
4 int *j;
j = 5; /* Valid  good practice .*
6 *It accepts address. */
printf(j is : %dn, j);// prints address pointed
8 //by the pointer variable
return 0;
10 }
✌
✆
✞
j is : 5
✌
✆
As pointers holds the address of other variables or objects, hence what ever value is
assigned to pointers is treated as memory address. Note that, addresses are represented
278 Array  Pointer
in hexa-decimal form, hence all other values are converted into equivalent hexadecimal
values. Method of assigning a value to a pointer as shown below is invalid. This is due to
assigning value to an uninitialised pointer. An uninitialized pointer points to null memory
address. So, when we tries to update the value at the memory address that is pointed by
the pointer, it shows errors.
✞
1 int *j;// No address with pointer to point.
*j = 5;/* Invalid as it tries to alter value *
3 * stored at address pointed by j. *
*It is very bad practice . */
✌
✆
A pointer points to the memory location (address) where value is stored. Pointer does
not store value itself. So, pointer does not know where value is stored. If we try to do so,
the program either may crash or it damaged to the system. A best practice of assigning
a pointer is explained in the following example.
✞
#include stdio.h
2
int main () {
4 int i = 0;
int *j;
6 j = malloc (2 * sizeof (int));
j = 5; /* valid  good practice to assign address */
8 printf(j is : %dn, j);// prints address
j = 6; /* valid  good practice to assign address */
10 printf(j is : %dn, j);// prints address
return 0;
12 }
✌
✆
✞
j is : 5
j is : 6
✌
✆
Another example
✞
#include stdio.h
2
int main (void ) {
4 int i;
int *p;
6 p = i; /* valid for best practice */
i = 10; /*i is now 10 */
8 *p = 20; /* valid*/
/* prints 20*/
10 printf(i is %dn, i);
/* Prints value stored at address pointed by the pointer.*/
12 printf(i is %dn, *p);
return 0;
14 }
✌
✆

More Related Content

PDF
c programming
PDF
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...
PDF
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
PPTX
Unit 3
PDF
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
PDF
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
PDF
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...
PDF
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
c programming
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
Unit 3
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...

What's hot (20)

DOC
C tech questions
DOCX
C interview question answer 2
PPTX
C++ Pointers
PDF
C++ L05-Functions
PDF
Recursion to iteration automation.
PPT
Fp201 unit5 1
PDF
C++ L07-Struct
PDF
C++ L06-Pointers
PDF
C++ L04-Array+String
PDF
C++ Programming - 11th Study
PDF
Modern C++ Concurrency API
PDF
C aptitude scribd
PDF
C++ L03-Control Structure
PDF
C++ L01-Variables
DOCX
Arrry structure Stacks in data structure
PDF
C++ L08-Classes Part1
PDF
Array notes
PPTX
functions of C++
PPT
Cquestions
PDF
Stl algorithm-Basic types
C tech questions
C interview question answer 2
C++ Pointers
C++ L05-Functions
Recursion to iteration automation.
Fp201 unit5 1
C++ L07-Struct
C++ L06-Pointers
C++ L04-Array+String
C++ Programming - 11th Study
Modern C++ Concurrency API
C aptitude scribd
C++ L03-Control Structure
C++ L01-Variables
Arrry structure Stacks in data structure
C++ L08-Classes Part1
Array notes
functions of C++
Cquestions
Stl algorithm-Basic types
Ad

Similar to c programming (20)

PPTX
Lecture 24 PART 1.pptxkhfwraetrsytfyugiuihjojiiyutdruot8
DOCX
Unitii string
PPT
Strings
PPTX
CSE 1102 - Lecture_7 - Strings_in_C.pptx
PPT
CP-STRING.ppt
PPT
CP-STRING (1).ppt
PPT
CP-STRING.ppt
PPTX
programming for problem solving using C-STRINGSc
PPT
14 strings
PDF
Principals of Programming in CModule -5.pdfModule-4.pdf
PPT
Strings(2007)
PPTX
Module-2_Strings concepts in c programming
PPTX
Slide -231, Math-1151, lecture-15,Chapter, Chapter 2.2,2.3, 5.1,5.2,5.6.pptx
PPT
strings
PDF
Strings part2
PDF
STRINGS IN C MRS.SOWMYA JYOTHI.pdf
PDF
[ITP - Lecture 17] Strings in C/C++
PPTX
introduction to strings in c programming
PPTX
Strings cprogramminglanguagedsasheet.pptx
PPTX
Computer Programming Utilities the subject of BE first year students, and thi...
Lecture 24 PART 1.pptxkhfwraetrsytfyugiuihjojiiyutdruot8
Unitii string
Strings
CSE 1102 - Lecture_7 - Strings_in_C.pptx
CP-STRING.ppt
CP-STRING (1).ppt
CP-STRING.ppt
programming for problem solving using C-STRINGSc
14 strings
Principals of Programming in CModule -5.pdfModule-4.pdf
Strings(2007)
Module-2_Strings concepts in c programming
Slide -231, Math-1151, lecture-15,Chapter, Chapter 2.2,2.3, 5.1,5.2,5.6.pptx
strings
Strings part2
STRINGS IN C MRS.SOWMYA JYOTHI.pdf
[ITP - Lecture 17] Strings in C/C++
introduction to strings in c programming
Strings cprogramminglanguagedsasheet.pptx
Computer Programming Utilities the subject of BE first year students, and thi...
Ad

More from Arun Umrao (20)

PDF
maths_practice_sheet_28.12.23 (copy).pdf
PDF
Function Analysis v.2
PDF
Average value by integral method
PDF
Xcos simulation
PDF
Work and energy
PDF
Units of physical quantities
PDF
Scilab help book 2 of 2
PDF
Scilab help book 1 of 2
PDF
Notes of Java
PDF
Modelica programming help book
PDF
Measurements and errors
PDF
Linear motion for k12 students
PDF
Gnu octave help book 02 of 02
PDF
Gnu octave help book 01 of 02
PDF
Fortran programming help book
PDF
Force and its application for k12 students
PDF
Electric field for k12 student
PDF
Dictionary of physics
PDF
Decreasing and increasing function
PDF
Circular motion
maths_practice_sheet_28.12.23 (copy).pdf
Function Analysis v.2
Average value by integral method
Xcos simulation
Work and energy
Units of physical quantities
Scilab help book 2 of 2
Scilab help book 1 of 2
Notes of Java
Modelica programming help book
Measurements and errors
Linear motion for k12 students
Gnu octave help book 02 of 02
Gnu octave help book 01 of 02
Fortran programming help book
Force and its application for k12 students
Electric field for k12 student
Dictionary of physics
Decreasing and increasing function
Circular motion

Recently uploaded (20)

PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
PTS Company Brochure 2025 (1).pdf.......
PPTX
Transform Your Business with a Software ERP System
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
Nekopoi APK 2025 free lastest update
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
System and Network Administration Chapter 2
PPTX
ai tools demonstartion for schools and inter college
PPTX
Essential Infomation Tech presentation.pptx
PDF
Digital Strategies for Manufacturing Companies
PPTX
history of c programming in notes for students .pptx
PPTX
L1 - Introduction to python Backend.pptx
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
System and Network Administraation Chapter 3
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
How Creative Agencies Leverage Project Management Software.pdf
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Design an Analysis of Algorithms I-SECS-1021-03
PTS Company Brochure 2025 (1).pdf.......
Transform Your Business with a Software ERP System
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Nekopoi APK 2025 free lastest update
Wondershare Filmora 15 Crack With Activation Key [2025
System and Network Administration Chapter 2
ai tools demonstartion for schools and inter college
Essential Infomation Tech presentation.pptx
Digital Strategies for Manufacturing Companies
history of c programming in notes for students .pptx
L1 - Introduction to python Backend.pptx
Which alternative to Crystal Reports is best for small or large businesses.pdf
System and Network Administraation Chapter 3
How to Migrate SBCGlobal Email to Yahoo Easily
How Creative Agencies Leverage Project Management Software.pdf
Navsoft: AI-Powered Business Solutions & Custom Software Development
VVF-Customer-Presentation2025-Ver1.9.pptx
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free

c programming

  • 1. 1.8. STRINGS 151 ✞ Type ’e’ for encrypt & ’d’ for decrypt : e ✌ ✆ ✞ Type ’e’ for encrypt & ’d’ for decrypt : f Unknown procedure . ✌ ✆ strcpy This function copies the string from source into destination. The size of the destination object shall be sufficiently large to hold the source string. If size of destination object is deficient of space, an overflow error occurs. The syntax of strcpy() is ✞ char *strcpy(char *restrict dest , 2 const char *restrict src); ✌ ✆ Note, source of strcpy should be string. It is recommended that strncpy() should be used instead of strcpy(), to avoid buffer overflow. A simple example is ✞ #include <stdio.h> 2 #include <string.h> 4 int main () { /* initialize a char variable */ 6 char str [80]; /* copy string The to variable .*/ 8 strcpy(str , "The "); /* concate the string India with The */ 10 strcat(str , "India "); strcat(str , "is "); 12 strcat(str , "developing ."); /* put output at the console */ 14 puts (str); return 0; 16 } ✌ ✆ ✞ The India is developing . ✌ ✆ An example which copies the contents of one array into other array without using strcpy() function is given below. In this example, one by one character of array ‘strA’ are copied into array ‘strB’. When array ‘strA’ encounters the null character, copying is halted. ✞ 1 #include <stdio.h> 3 int main () { char strA [50], strB [50]; 5 int i; printf("nEnter string s1: "); 7 scanf("%s", strA ); /* Copy one by one character into strB .*/
  • 2. 152 Basic C 9 for (i = 0; strA [i] != ’0’; i++) { strB [i] = strA [i]; 11 } /* Add null character to strB at the end.*/ 13 strB [i] = ’0’; printf("nString s2: %s", strB ); 15 return 0; } ✌ ✆ Following is a strcpy() example that is used to trim the white spaces from the left and right hand side of a string. ✞ #include <stdio.h> 2 #include <string.h> #include <ctype.h> 4 /* Trimming leading and trailing white spaces. */ 6 char *trim (char * s) { /* Initialize start , end pointers */ 8 char *s1 = s, *s2 = &s[strlen(s) - 1]; 10 /* If last char is a white space and there* * is a previous char that is also a white* 12 * space then reduce the pointer by one * * for each white space. */ 14 while (( isspace (*s2)) && (s2 >= s1)) s2 --; 16 /* Finally we find the pointer value for * * last character other than a white space.*/ 18 /* Add end of line . */ 20 *(s2 + 1) = ’0’; 22 /* If first char is a white space and there* * is next char that is also a white space * 24 * then increase the pointer position by * * one for each white space. */ 26 while (( isspace (*s1)) && (s1 < s2)) s1 ++; 28 /* Copy rest of string to s */ 30 strcpy(s, s1); return s; 32 } 34 int main (int argc , char *argv [ ]) { char *s; 36 char string [100] = " 1arun2 "; printf("The original string is :%s:n", string); 38 s = trim (string); printf("The trimmed string is :%s:n", s);
  • 3. 1.8. STRINGS 153 40 return 0; } ✌ ✆ ✞ The original string is : 1arun 2 : The trimmed string is :1 arun 2: ✌ ✆ strlen Synopsis of strlen() function is ✞ size _t strlen(const char *s); ✌ ✆ The strlen() function shall compute the number of bytes in the string to which ‘s’ points, not including the terminating null byte. It returns the number of bytes in the string. No value is used to indicate an error. A simple example is ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 char Input [256]; printf("Enter a string : "); 7 gets ( Input); printf("The string length is %u characters long .n", 9 (unsigned ) strlen(Input)); return 0; 11 } ✌ ✆ ✞ Enter a string : a The string length is 1 characters long . ✌ ✆ strlen() counts only those cells in which string or character is stored. The counting of strlen() is stopped when, it encountered the cell of null character. We can used several methods to find the string length without using strlen function. ✞ #include <stdio.h> 2 #include <stdlib.h> 4 int main (void ) { int n = 0, c; 6 /* get string to be counted */ printf("Enter the string : "); 8 while ((c = getchar ()) != ’n’) { n++; 10 } printf("The string length is %d.n", n); 12 return 0; } ✌ ✆
  • 4. 154 Basic C ✞ Enter the string : arun kumar The string length is 10. ✌ ✆ A new example that uses array and strlen() function to get reverse of the supplied string. Actually in this example, strlen() function is used to get the length of the string. After that the characters of the string are printed in reverse order. ✞ #include <stdio.h> 2 #include <stdlib.h> 4 int main (void ) { char rs [1000]; // string to reversed . 6 /* get string to be reversed */ printf("Enter the string to be reversed : "); 8 scanf("%s", rs); printf("The reversed string is : "); 10 /* While array is not triggered with space*/ int n = strlen(rs); 12 while (n > 0) { printf("%c", rs[n - 1]); 14 n--; } 16 return 0; } ✌ ✆ ✞ Enter the string to be reversed : arun The reversed string is : nura ✌ ✆ In following example, classical method is used to find the length of a string. In this example, we count the characters in a string until a null terminating character is not obtained. After each counting, counter is increased by one. At last the counting value is the actual length of the string. ✞ #include <stdio.h> 2 int main (void ) { 4 char name [ ] = "NAME arun kr"; int i = 0; 6 while (name [i] != NULL ) i++; 8 printf("The length of string "%s" is %d.", name , i); return 0; 10 } ✌ ✆ ✞ The length of string "NAME arun kr" is 12. ✌ ✆ The following example is rewritten in which string pointer is passed to a function where string length is computed. The string length is returned to the main function and printed in output console.
  • 5. 1.8. STRINGS 155 ✞ 1 #include <stdio.h> 3 int StrLen(char * str) { int i = 0; 5 while (str[i] != ’0 ’) { i++; 7 } return i; 9 } 11 int main () { char str[ ] = "This is my string."; 13 int i; i = StrLen(str); 15 printf("The length of string is %d.n", i); return 0; 17 } ✌ ✆ ✞ The length of string is 18. ✌ ✆ The memory used by given string may also be retrieve by using keyword ‘sizeof’ as shown in example below. ✞ 1 #include <stdio.h> #include <string.h> /* provides strlen () prototype */ 3 #define PRAISE "Hi!" 5 int main (void ) { char name [40]; 7 printf("What ’s your name ?n"); scanf("%s", name ); 9 printf("Hello , %s. %sn", name , PRAISE); printf("Name has %d letters & occupies %d memory cells.n", 11 strlen(name ), sizeof name ); printf("The praise has %d letters ",strlen(PRAISE)); 13 printf("and occupies %d memory cells.n", sizeof PRAISE); return 0; 15 } ✌ ✆ ✞ What ’s your name ? Arun Hello , Arun . Hi! Name has 4 letters & occupies 40 memory cells. The praise has 3 letters and occupies 4 memory cells. ✌ ✆ strncat strncat() function concatenate specific number of characters into destination from the source. Synopsis of this function is
  • 6. 156 Basic C ✞ 1 char *strncat (char *s1 , const char *s2 , size_t n); ✌ ✆ The strncat() function shall not append more than ‘n’ bytes. A simple example is ✞ 1 #include <stdio.h> 3 int main () { char str1 [20]; 5 char str2 [20]; 7 strcpy(str1 , "Hello"); strcpy(str2 , "Worlddddddddd "); 9 printf("Concatenated string is : %sn", strncat (str1 , str2 , 4)); 11 printf("Final string is : %sn", str1 ); 13 return 0; } ✌ ✆ ✞ Concatenated string is : HelloWorl Final string is : HelloWorl ✌ ✆ strncmp The strncmp function syntax is ✞ int strncmp (const char *s1 , const char *s2 , size_t n); ✌ ✆ The strncmp() function shall compare not more than n bytes (bytes that follow a null byte are not compared) from the array pointed-by ‘s1’ into the array pointed-by ‘s2’. The sign of a non-zero return value is determined by the sign of the difference between the values of the first pair of bytes (both interpreted as type unsigned char) that differ in the strings being compared. See strcmp() for an explanation of the return value. This function is as useful in comparisons, as the strcmp function is. A simple example is ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 if (strncmp ("arun ", "Arun ", 2) ==0) { printf("Two strings are equal."); 7 } else { printf("Two strings are not equal."); 9 } return (0); 11 } ✌ ✆ ✞ Two strings are not equal. ✌ ✆
  • 7. 1.8. STRINGS 157 strncpy The syntax of strncpy() function is ✞ 1 char *strncpy (char *s1 , const char *s2 , size_t n); ✌ ✆ The strncpy() function shall copy not more than ‘n’ bytes (bytes that follow a null byte are not copied) from the array pointed-by ‘s2’ into the array pointed-by ‘s1’. A simple example is ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 /* initialize an experimental string */ char str[ ] = "This is a simple string"; 7 char * pch; /* get first occurace of simple*/ 9 pch = strstr(str , " simple"); /* copy NAGPUR from the point of simple upto two places.*/ 11 strncpy (pch , "NAGPUR", 2); /* copy NAGPUR from the point of simple upto four places.*/ 13 strncpy (pch , "NAGPUR", 4); puts (str); 15 /* copy NAGPUR from the point of simple upto six places.*/ strncpy (pch , "NAGPUR", 6); 17 puts (str); return 0; 19 } ✌ ✆ ✞ This is a NAmple string This is a NAGPle string This is a NAGPUR string ✌ ✆ In the above program, line ✞ 1 strncpy(pch , "NAGPUR", 2); ✌ ✆ copied first two characters from the “NAGPUR” at 11th and 12th place of the string ‘str’ as shown below: strncpy(pch, “NAGPUR”, 2) s i m p l e s N A G P U R 0 Similarly, in the above program, line ✞ 1 strncpy(pch , "NAGPUR", 6); ✌ ✆
  • 8. 158 Basic C copied first six characters from the “NAGPUR” into ‘str’ from 11th to 16th place of the string ‘str’ as shown below: strncpy(pch, “NAGPUR”, 6) s i m p l e s N A G P U R 0 During the copying of strings, size of strings should be clearly defined, otherwise the actual string may terminate shortly as null terminator is added within the actual string as shown in the following example. ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 /* initialize an experimental string */ char str[ ] = "This is a simple string"; 7 char * pch; /* get first occurace of simple*/ 9 pch = strstr(str , " simple"); /* copy NAGPUR from the point of simple upto seven places.*/ 11 strncpy (pch , "NAGPUR", 7); puts (str); 13 return 0; } ✌ ✆ ✞ This is a NAGPUR ✌ ✆ strncpy(pch, “NAGPUR”, 7) s i m p l e s N A G P U R 0 strrchr The strrchr() function searches string for the last occurrence of a character. The null character that represents to the termination of string, is also included in the search. The prototype of strrchr() function is ✞ 1 char *strrchr (const char *s, int c); ✌ ✆ strrchr is similar to strchr(), except the string is searched right to left. A simple example is
  • 9. 1.8. STRINGS 159 ✞ 1 #include <stdio.h> 3 int main () { char *s; 5 char buf [ ] = "This is a testing "; 7 s = strrchr (buf , ’t’); 9 if (s != NULL ) printf("found a ’t’ at %sn", s); 11 return 0; 13 } ✌ ✆ ✞ found a ’t’ at ting ✌ ✆ Here is another example that returns the position in a string where a delimiter is found. ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 char str[ ] = "This is my string"; char match[ ] = "i"; 7 int i; int c = 0; 9 for (i = 0; i < strlen(str); i++) { if (str[i] == match[c] && c < strlen(match)) { 11 c++; } else { 13 c = 0; } 15 if (c == strlen(match)) { printf("Pattern matched after %d charsn", 17 i - strlen(match) + 1); } 19 } return 0; 21 } ✌ ✆ ✞ Pattern matched after 2 chars Pattern matched after 5 chars Pattern matched after 14 chars ✌ ✆ strstr The syntax of strstr() function is
  • 10. 160 Basic C ✞ 1 char *strstr(const char *string , const char *sub -str); ✌ ✆ The strstr() function shall locate the first occurrence in the string pointed-by ‘string’ of the sequence of bytes (excluding the terminating null byte) in the string pointed-by ‘sub-str’. It returns the pointer (or may say the address) of the first occurrence of the sub-string. A simple example is ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 /* initialize an experimental string */ char str[ ] = "This is a simple string"; 7 char * pch; /* get first occurance of simple */ 9 pch = strstr(str , " simple"); puts (pch); 11 return 0; } ✌ ✆ ✞ simple string ✌ ✆ pch = strstr(str, ”simple”); T h i s i s a s i m p l e s t r i n g 0 pch s i m p l e s t r i n g 0 strtok The syntax of strtok function is ✞ 1 char *strtok(char *restrict s1 , const char *restrict delimiters ); ✌ ✆ A sequence of calls to strtok() breaks the string pointed-by ‘s1’ into a sequence of tokens, each of which is delimited by a byte from the string pointed-by delimiters. This function returns the address of memory location where tokenised string is stored. first cA simple example is ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 /* experimental string */ char str[ ] = "- This is my country .";
  • 11. 1.8. STRINGS 161 7 /* pointer for string tokenization */ char * pch;/*Do not need memory allocation , as it* 9 *has to point the memory address * *being returned by strtok function . */ 11 printf("String "%s" is splitted into tokens:n", str); /* break experimental string with * 13 * spacecomma dot and doublequote */ pch = strtok(str , " ,.-"); 15 while (pch != NULL ) { printf("%sn", pch); 17 pch = strtok(NULL , " ,.-"); } 19 return 0; } ✌ ✆ ✞ String "- This is my country ." is splitted into into tokens: This is my country ✌ ✆ Here is an example which splits the string by a delimiter without using strtok() function. In this example, a string is read character by character and when a read character is equal to the delimiter, a new line is started. ✞ 1 #include <stdio.h> 3 int main (int argc , char *argv [ ]) { if (argv [1] == NULL ) { 5 printf("Use <utility .exe > <string in double quote > <delimiter >.n"); exit (0); 7 } /* get the commandline string*/ 9 char *Str = argv [1]; char *Del = argv [2]; 11 printf("The delimiter is ’%s ’.n", Del); printf("The broken strings are : nn", Del); 13 int i = 0; while (Str[i] != NULL ) { 15 if (Str[i] == Del [0]) { printf("n"); 17 i++; } 19 printf("%c", Str[i]); i++; 21 } printf("nnThe length of string supplied is %d.n", i); 23 return 0; } ✌ ✆
  • 12. 162 Basic C ✞ executable .exe "This is my name " " " This is my name The length of string supplied is 15. ✌ ✆ strtod The strtod(), strtof (), and strtold() functions convert the initial portion of the string pointed-by pointer to double, float, and long double representation, respectively. The return value is numerical value and pointer stores the rest of string. ✞ 1 #include <stdio.h> #include <stdlib.h> 3 int main () { 5 char str [30] = "20.30300 Rs are spent."; char *ptr; 7 double ret; 9 ret = strtod(str , &ptr); printf("The Rs in ( double) is %lfn", ret); 11 printf("|%s|n", ptr); 13 return (0); } ✌ ✆ ✞ The Rs in (double) is 20.303000 | Rs are spent.| ✌ ✆ 1.9 Function Function in C a group of statements and expressions which accepts inputs, analyse them according to the statements and expressions, and return the result. ✞ int sum(int a, int b){ 2 <function body expressions > } ✌ ✆ A function is like a black box. It takes inputs and do something and throws an output. A function may be declared with or without definition as shown below: ✞ 1 int myFunc (); // Function declared without definition int myFunc (){} // Function declared with definition ✌ ✆
  • 13. 1.9. FUNCTION 163 1.9.1 Function Arguments A functions accepts inputs through its arguments. A function with two arguments (or parameters) is defined as ✞ int sum(int a, int b); ✌ ✆ These parameters in a function definition are called formal arguments. Here, int a, int b are known as formal arguments. During the defining of a function, each argument must be identified by its type. For example, to supply two integer arguments to a function, it shall be defined like ✞ 1 int sum(int a, int b); ✌ ✆ while, the definition of function as given below is illegal. ✞ 1 int sum(int a, b);// Illegal definition ✌ ✆ Here, second argument ‘b’ is type unidentified. A function can be called from anywhere by supplying actual arguments. The supplied argument to a function are type casted according to the type of the function argument. For example, when a function type ✞ 1 int sum(int a, int b); ✌ ✆ is called as ✞ 1 sum (2.5, 2); ✌ ✆ then the function accepts argument value (or actual arguments) 2.5 as a = 2 because, ar- gument a is an integer type and supplied argument is float type. While, b = 2. Therefore, decimal part of the float value is truncated. See example below. ✞ 1 #include <stdio.h> 3 /* Sum function with formal arguments */ int sum(int a, int b) { 5 int f; f = a + b; 7 return f; } 9 int main (int argc , char *argv [ ]) { 11 int g; /* Sum function with actual arguments */ 13 g = sum (2.5, 2); printf("Sum of %f and %d is %dn", 2.5, 2, g); 15 return 0; } ✌ ✆ ✞ Sum of 2.5 and 2 is 4 ✌ ✆
  • 14. 164 Basic C Two dimensional arrays of integer type may also be passed as function argument. Two dimensional, integer type and static size array is passed to function as shown below: ✞ 1 #include <stdio.h> 3 void myFunc(int myArray [3][3]) { int i, j; 5 for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { 7 printf("%d t", myArray[i][j]); } 9 printf("n"); } 11 } 13 int main () { int myArray [][3] = { 15 {1, 2, 3}, {4, 5, 6}, 17 {7, 8, 9} }; 19 myFunc(myArray); return 0; 21 } ✌ ✆ ✞ 1 2 3 4 5 6 7 8 9 ✌ ✆ If height of the two dimensional array is dynamic and only width is fixed then two dimensional integer type array is passed to a function. The unknown dimension of the array should be passed to the function as its another parameter. ✞ 1 #include <stdio.h> 3 void myFunc(int myArray [][3] , int m) { int i, j; 5 for (i = 0; i < m; i++) { for (j = 0; j < 3; j++) { 7 printf("%d t", myArray[i][j]); } 9 printf("n"); } 11 } 13 int main () { int myArray [3][3] = { 15 {1, 2, 3}, {4, 5, 6}, 17 {7, 8, 9} };
  • 15. 1.9. FUNCTION 165 19 myFunc(myArray , 3); return 0; 21 } ✌ ✆ ✞ 1 2 3 4 5 6 7 8 9 ✌ ✆ A dynamic two dimensional integer type array may passed to a function as its argument in pointer form. Remember that as two dimensional array passed to function a pointer only and the called function does not know the actual size of the passed array. Therefore, dimensions of the array must be passed as another parameters of the function. ✞ 1 #include <stdio.h> 3 /* Catch myArray pointer as parameter of * * function . myr parameter points to passed* 5 * array as 1D array not as 2D array. */ void myF(int *mAr , int m, int n) { 7 int i, j; for (i = 0; i < m; i++) { 9 for (j = 0; j < n; j++) { /* Print the array elements row by row.*/ 11 printf("%d ", *(( mAr + i * n) + j)); } 13 printf("n"); } 15 } 17 int main () { int myArray [][3] = { 19 {4, 5, 6}, {1, 2, 3}, 21 {9, 8, 7} }; 23 /* Pass myArray as a pointer. */ myF(( int *) myArray , 3, 3); 25 return 0; } ✌ ✆ ✞ 4 5 6 1 2 3 9 8 7 ✌ ✆
  • 16. 166 Basic C myArray[m][n]= 11 12 13 14 15 21 22 23 24 25 31 32 33 34 35 41 42 43 44 45 51 52 53 54 55 i j myF((int *) myArray, ...) Pass Array to Function In above example, array is passed as pointer and the address of the array pointer is catches by the function as its parameter. Notice that, inside the function, array pointer does not represents to two dimensional array but represents to one dimensional array as a group of bytes in row by row order. This is why, in this function the dimensions of the array are passed via two additional parameters. These parameters are used to control the printing of each element of the passed array. void myF(int *mAr, ...){...} 11 12 13 14 15 21 22 23 24 25 ... *((mAr+i*n)+j) *((mAr+i*n)+j) Array as Argument Now, again, in C, a function without any argument can be compiled ans run by calling with any number of arguments. See the example below: ✞ 1 #include <stdio.h> 3 void testFun () { } // Function declared without arguments 5 int main (void ){ // Function called with three argument . 7 testFun (10, "x", "Y"); return 0; 9 } ✌ ✆ But if the argument of prototype function is void type then the program fails to compile and run. See below: ✞ 1 #include <stdio.h> 3 void testFun (void ) { } // Function declared with void arguments 5 int main (void ){ // Function called with three argument . 7 testFun (10, "x", "Y"); return 0; 9 } ✌ ✆
  • 17. 1.9. FUNCTION 167 1.9.2 Function Prototype The declaration of a function prototype tell the compiler three important things about it: 1. to expect to encounter them further down the program; 2. the return types of the function, e.g. void, int or double; 3. the number and kind of arguments the function is to handle; The parameter names listed in a function’s prototype may be same as in the function’s declaration or not. Function prototype allows to omit the variable name in its arguments. The legal function prototyping are ✞ 1 int sum(int , int); /* Legal prototype .*/ int sum(int a, int b); /* Legal prototype .*/ 3 int sum(a, int b); /* Illegal prototype .*/ int sum(int *, int *a); /* Legal prototype with pointer array.*/ 5 int sum(int *, int &a); /* Illegal prototype with address of a*/ int sum(int [ ], int a[ ]); /* Legal prototype with array.*/ ✌ ✆ Function prototyping is required when a function is called from the body of another function which is defined above the called function. It also needed to be declared if function is envoked before its definition as shown in the below example. ✞ #include <stdio.h> 2 /* Prototype is required .*/ void swap (int * u, int * v); 4 int main (void ) { 6 int x = 5, y = 10; printf("Originally x = %d and y = %d.n", x, y); 8 swap (&x, &y); /* Send addresses to function */ printf("Now x = %d and y = %d.n", x, y); 10 return 0; } 12 void swap (int * u, int * v) { 14 int temp ; temp = *u; /* temp gets value that u points to */ 16 *u = *v; /* Store the value of v at address of x*/ *v = temp ; /* Store the value of u at address of y*/ 18 } ✌ ✆ ✞ Originally x = 5 and y = 10. Now x = 10 and y = 5. ✌ ✆ If prototype is not declared, then the compiler shows errors as in the following example, function is envoked before the definition of the function.
  • 18. 168 Basic C ✞ #include <stdio.h> 2 /* Prototype is disabled .*/ // void swap (int * u, int * v); 4 int main (void ) { 6 int x = 5, y = 10; printf("Originally x = %d and y = %d.n", x, y); 8 swap (&x, &y); /* send addresses to function */ printf("Now x = %d and y = %d.n", x, y); 10 return 0; } 12 void swap (int * u, int * v) { 14 int temp ; temp = *u; /* temp gets value that u points to */ 16 *u = *v; /* Store the value of v at address of x*/ *v = temp ; /* Store the value of u at address of y*/ 18 } ✌ ✆ Again, if a function is called from the body of another function which is defined below to the called function, then declaration of prototype is not required. ✞ #include <stdio.h> 2 void swap (int * u, int * v) { 4 int temp ; temp = *u; /* temp gets value that u points to */ 6 *u = *v; /* Store the value of v at address of x*/ *v = temp ; /* Store the value of u at address of y*/ 8 } 10 int main (void ) { int x = 5, y = 10; 12 printf("Originally x = %d and y = %d.n", x, y); swap (&x, &y); /* send addresses to function */ 14 printf("Now x = %d and y = %d.n", x, y); return 0; 16 } ✌ ✆ ✞ Originally x = 5 and y = 10. Now x = 10 and y = 5. ✌ ✆ Another point is to be remembered that C compiler assumes a function as integer return type by default. If user defined function is declared as integer type, then C compiler does not failed to compile a function without prototype declaration. If user defined function returns other values then compiler fails to compile the program. The following example compiled successfully. ✞ #include <stdio.h> 2 /* Declaring prototype */
  • 19. 1.9. FUNCTION 169 char myFunc (); 4 int main (void ) { 6 /* Calling function of integer type return.*/ printf("Calling function myFunc()n"); 8 printf("Returned value is %c", myFunc ()); return 0; 10 } 12 /* Declaring function of char type return.*/ char myFunc () { 14 return ’A’; } ✌ ✆ ✞ Calling function myFunc () Returned value is A ✌ ✆ Above function is re-written without declaring prototype. This program is failed to compile. ✞ #include <stdio.h> 2 int main (void ) { 4 /* Calling function of integer type return.*/ printf("Calling function myFunc()n"); 6 printf("Returned value is %c", myFunc ()); return 0; 8 } 10 /* Declaring function of char type return.*/ char myFunc () { 12 return ’A’; } ✌ ✆ There is no problem if the function is declared with integer return type. See the example below which is modified form of above function. ✞ 1 #include <stdio.h> 3 int main (void ) { /* Calling function of integer type return.*/ 5 printf("Calling function myFunc()n"); printf("Returned value is %c", myFunc ()); 7 return 0; } 9 /* Declaring function of integer type return.*/ 11 int myFunc () { return ’A’; 13 } ✌ ✆
  • 20. 170 Basic C ✞ Calling function myFunc () Returned value is A ✌ ✆ Compiler does not care about parameters of the declared function prototype. The com- piler will not be able to perform compile-time checking of argument types. The validity of arguments is checked during the program run time and sometime program returns garbage value. ✞ #include <stdio.h> 2 int main (void ) { 4 /* Calling function of integer type return.*/ printf("Calling function myFunc()n"); 6 printf("Returned value is %c", myFunc (65) ); return 0; 8 } 10 /* Declaring function of integer type return.*/ int myFunc(int i, int j) { 12 return i + j; } ✌ ✆ 1.9.3 Function Types In old C standards, each function was considered as integer type, while in new implemen- tation of C standards, the type of the function may be integer, float, double, character or void. Declaration of a function type is based on the return value of the function not on the argument type. See example below: ✞ 1 #include <stdio.h> /* Integer type function .*/ 3 int max(int a, int b) { if (a > b) 5 return a; else 7 return b; } 9 int main (int argc , char *argv [ ]) { 11 /* integer specifier required to * *print return value from function .*/ 13 printf("Max of %d and %d is %dn", 2, 3, max(2, 3)); return 0; 15 } ✌ ✆ ✞ Max of 2 and 3 is 3 ✌ ✆
  • 21. 1.9. FUNCTION 171 In function ‘max’, two arguments are taken as inputs as integer and between them, greater is returned as integer. Hence, here the function is declare as integer type. If the same function is declared as float type then return value is a float value not integer value. ✞ 1 #include <stdio.h> /* Float type function .*/ 3 float max(int a, int b) { if (a > b) 5 return a; else 7 return b; } 9 int main (int argc , char *argv [ ]) { 11 /* Float specifier required to print* *return value from function . */ 13 printf("Max of %d and %d is %fn", 2, 3, max(2, 3)); return 0; 15 } ✌ ✆ ✞ Max of 2 and 3 is 3.0000 ✌ ✆ In case of void functions, the function should return with NULL value even if return keyword is used inside the function. This type of function do something according to its expression and stores the result in global variable. ✞ 1 #include <stdio.h> int f; 3 void sum(int a, int b) { 5 f = a+b; /* Use of return keyword without any value.*/ 7 return; } 9 int main (int argc , char *argv [ ]) { 11 sum(2, 3); printf("Sum of %d and %d is %dn", 2, 3, f); 13 return 0; } ✌ ✆ ✞ Sum of 2 and 3 is 5 ✌ ✆ Use of return keyword in following manner are valid in void type functions. ✞ 1 return; /* Legal return*/ return ""; /* Legal return */ 3 return NULL ; /* Legal return */ return "; /* Illegal , " is null character code */ ✌ ✆
  • 22. 172 Basic C return keyword is somewhat like exit keyword. After return keyword, anything inside an expression block is skipped during program execution. Function returns the assigned value and exits. ✞ #include <stdio.h> 2 int ret(); 4 int main (void ) { 6 ret(); return 0; 8 } 10 int ret() { int i = 0; 12 int loops = 15; printf("Loop count is %dn", loops); 14 while (i < loops) { printf("i is %dn", i); 16 if (i == 7) { printf("Returning from the function at i=%dn", i); 18 printf("reaching before the loop value %dn", loops); return 0; 20 } i++; 22 } return 0; 24 } ✌ ✆ ✞ Loop count is 15 i is 0 i is 1 i is 2 i is 3 i is 4 i is 5 i is 6 i is 7 Returning from the function at i=7 reaching before the loop value 15 ✌ ✆ A function with void return type can not be called through printf. For example ✞ 1 #include <stdio.h> #include <stdlib.h> 3 /* function return type is void */ 5 void myF() { printf("myF"); 7 }
  • 23. 1.9. FUNCTION 173 9 int main () { int i = 5, j = 3; 11 /* invalid use of void type function */ printf("%s", myF()); 13 return 0; 15 } ✌ ✆ program failed to compile and returns compile time error “invalid use of void”. Never Reach Condition A function with return keyword, returns either NULL or some alpha-numeric value after successful execution. Execution of function-script is terminated after first successful return. If a function is designed in such manner that it has to reached to only fixed return keywords then other return keywords if used are never reached by the compiler. See the example given below: ✞ 1 #include <stdio.h> 3 int executeMe (int i) { if (i <= 10) { /* If i is less than or equal to 10 */ 5 return 0; } else { /* Otherwise */ 7 return 1; } 9 return -1; /* Mever reached */ } 11 int main () { 13 printf("%dn", executeMe (10) ); printf("%dn", executeMe (15) ); 15 printf("%dn", executeMe (1)); return 0; 17 } ✌ ✆ ✞ 0 1 0 ✌ ✆ 1.9.4 Function Recursion In C, a function can be called recursively, i.e. in nested form from within its body, without using loop functions, i.e. for, while or do-while etc. See the example given below: ✞ 1 #include <stdio.h> int recFunc (int i, int j); 3 int recFunc (int i, int j) { 5 if (i == 0) { return (2 + j);
  • 24. 174 Basic C 7 } else { return recFunc(i - 1, j + 1); 9 } } 11 int main (int argc , char ** argv ) { 13 int k = recFunc (4, 6); printf("%d", k); 15 return 0; } ✌ ✆ ✞ 12 ✌ ✆ In above example, function ‘recFunc’ takes two arguments and checks the conditions for its first argument. If it is true then it returns the sum of ‘2’ and second argument and exits. Otherwise it returns the function ‘recFunc’ with new values of its two arguments. As function calls itself, hence a loop like recursion is observed. There should be a condition to be met and break the function recursion otherwise there shall be no return value. See the following examples, ✞ 1 #include <stdio.h> int recFunc (int i, int j); 3 /* This type of recursion is not acceptable .*/ 5 int recFunc (int i, int j) { /*No Condition , No return value.*/ 7 return recFunc(i - 1, j + 1); } 9 int main (int argc , char ** argv ) { 11 int k = recFunc (4, 6); printf("%d", k); 13 return 0; } ✌ ✆ If condition in the recursive function is not met then there is no return value from the function. In the following example, if condition is never met therefore, there shall be no return value from the recursive function. ✞ #include <stdio.h> 2 int recFunc (int i, int j); 4 int recFunc (int i, int j) { /* Condition never met. No returned value.*/ 6 if (i == 0) { return (2 + j); 8 } else { return recFunc(i, j + 1); 10 } }
  • 25. 1.9. FUNCTION 175 12 int main (int argc , char ** argv ) { 14 int k = recFunc (1, 6); printf("%d", k); 16 return 0; } ✌ ✆ There shall be no output on running of above two program. 1.9.5 Function As Argument A function can pass to another function as its argument. The synopsis of the passing of a function as argument to the other function tFunc() is given below: ✞ 1 void tFunc(<data type > (*< func pointer >)()); ✌ ✆ See the example : ✞ 1 #include <stdio.h> #include <math .h> 3 /* Here *fp is pointer of the function sqrt */ 5 void tFunc(char *name , double (*fp)()) { int n; 7 printf("Testing function %s:n", name ); printf("%s: %10sn", "n", "Square Root "); 9 printf(" --------------n"); for (n = 0; n < 10; n++) { 11 printf("%d: %11.6fn", n, (*fp)(( double) n)); } 13 } 15 int main () { tFunc("square root ", sqrt ); 17 return 0; } ✌ ✆ ✞ Testing function square root : n: Square Root -------------- 0: 0.000000 1: 1.000000 2: 1.414214 3: 1.732051 4: 2.000000 5: 2.236068 6: 2.449490 7: 2.645751 8: 2.828427 9: 3.000000 ✌ ✆
  • 26. 176 Basic C 1.9.6 Function Callback A callback is a piece of executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at some convenient time. In C, there is no “callback” yet they are implemented by using function pointers. Following example shows the possible call back. ✞ 1 #include <stdio.h> 3 /* This function is calledback from other function .*/ int DoubleIt (int a) { 5 return 2 * a; } 7 /* Pass DoubleIt function as argument named fPar .* 9 *The argument should be as function prototype . */ int myFunc(int (* fPar )(int)) { 11 int i = 10; fPar (i); 13 } 15 int main () { /* Pass function DoubleIt to myFunc */ 17 printf("Result is : %dn", myFunc(DoubleIt )); return 0; 19 } ✌ ✆ ✞ Result is : 20 ✌ ✆ The same above example is given in pointer format. ✞ 1 #include <stdio.h> 3 /* This function is calledback from other function .*/ int *DoubleIt (int a) { 5 int *i; i = (2 * a); 7 } 9 /* Pass DoubleIt function as argument named fPar .* *The argument should be as function prototype . */ 11 int *myFunc(int (* fPar )(int )) { int i = 10; 13 (* fPar )(i); } 15 int main () { 17 /* Pass function DoubleIt to myFunc */ printf("Result is : %dn", myFunc(DoubleIt )); 19 return 0; } ✌ ✆
  • 27. 1.9. FUNCTION 177 ✞ Result is : 20 ✌ ✆ A function may be called from its pointer index if function pointer is saved in function symbol table. See the example given below: ✞ 1 #include <stdio.h> #include <stdlib.h> 3 #include <dlfcn.h> 5 /* Memory allocation for 5 Function Pointers */ int (*FP [5]) (); 7 main (int argc , char **argv ) { 9 int i = 0; void * myLib; 11 /* Function pointer */ 13 void *fptr ; 15 /* Load function library */ myLib = dlopen("libtestdll .dll", RTLD_LAZY ); 17 /* Find the function object of function "bar"*/ 19 fptr = dlsym(myLib , "bar"); 21 /* Assign address of library function "bar"* *to all indexed function pointers (FP) */ 23 for (i = 0; i < 5; i++) { FP[i] = fptr ; 25 } 27 /* Call function from second FP address */ FP [1](); 29 /* Close Library */ 31 dlclose (myLib); 33 return 0; } ✌ ✆ ✞ called bar function from dll. ✌ ✆ 1.9.7 Memory Function Memory functions in C, deals with memory. These functions are used to store, copy and move data from one memory location to other memory location.
  • 28. 178 Basic C mmap To read or write to same file by two or more processes, mmap() function is used. Before mapping a file to memory, file descriptor is obtained by using open() function as given below: ✞ 1 int fd; fd=open ("<file name >", "<mode >"); ✌ ✆ The open function returns the file descriptor as integer value. ‘-1’ if it failed to open the file otherwise a positive integer as file handle. Now, mmap() is called to map the file as ✞ data = mmap (<address >, <size >, <prot >, <flags >, <file id >, <offset >); ✌ ✆ ‘address’ is the memory address where we want to mapped a file. By default its value is ‘0’ for automatic selection of address by the OS. ‘size’ is length of data of the file to be mapped. ‘prot’ is a kind of access/permission to the file. Its values are PROT READ for read only permission, PROT WRITE for write only permission and PROT EXEC for execute permissions. ‘flags’ controls the sharing of changes or just keep them private. The flag values are MAP SHARED or MAP PRIVATE for sharing and private mode respectively. ‘offset’ is initial position of the file from where mapping of file data to memory started. This value must be a multiple of the virtual memory page size. To get the page size, getpagesize() function is used. See the example below: ✞ 1 #include <stdio.h> #include <stdlib.h> 3 #include <sys/mman .h> #include <fcntl.h> 5 int main (int argc , char *argv []) { 7 int fd; char *data ; 9 /* Read only mode of file .*/ if ((fd = open ("a.txt", O_RDONLY )) == -1) { 11 printf("Unable to open file "); return 1; 13 } /* Map file in memory with read only permissions */ 15 data = mmap (0, 1024, PROT_READ , MAP_SHARED , fd , 0); if (* data == -1) { 17 printf("Unable to map file "); return 1; 19 } printf("Byte at offset %d is ’%c ’n", 0, data [0]) ; 21 return 0; } ✌ ✆ ✞ Byte at offset 0 is ’s’ ✌ ✆
  • 29. 1.9. FUNCTION 179 Each file which is mapped must be freed by using munmap function as ✞ 1 int munmap(<address >, <size >); ✌ ✆ Once the file is unmapped, data access with old file descriptor is not possible and will return segmentation fault error. If multiple protected access permissions are granted by using OR (|) operator in mmap() function, then the file access mode should be according the access granted. See the example below in which protected access mode is grated for read and write. Therefore, the file access mode in open() function is “rw” type (i.e. read and write type via O RDWR). ✞ 1 #include <stdio.h> #include <stdlib.h> 3 #include <sys/mman .h> #include <fcntl.h> 5 int main (int argc , char *argv []) { 7 int fd; char *data ; 9 /* Read and write mode of file .*/ if ((fd = open ("a.txt", O_RDWR)) == -1) { 11 printf("Unable to open file "); return 1; 13 } /* Map file in memory with read & write permissions */ 15 data = mmap (0, 1024, PROT_READ |PROT_WRITE , MAP_SHARED , fd , 0); if (* data == -1) { 17 printf("Unable to map file "); return 1; 19 } printf("Byte at offset %d is ’%c ’n", 0, data [0]) ; 21 data [10] = ’1’; printf("Byte at offset %d is ’%c ’n", 10, data [10]); 23 return 0; } ✌ ✆ ✞ Byte at offset 0 is ’a’ Byte at offset 10 is ’1’ ✌ ✆ File Mode Key Numeric Description O RDONLY 0 Read only access to file. O WRONLY 1 Write only access to file. O RDWR 2 Read and write access to file. Table 1.21: File access mode.
  • 30. 180 Basic C A segment of file may be mapped by using mmap function with setting file pointer by lseek function as given below: ✞ .... 2 for (j = 0; j <= bk; j++) { /* Map file for block size ‘bks’ from ‘offset’*/ 4 data = mmap (0, bks , PROT_READ | PROT_WRITE , MAP_SHARED , fd , offset); 6 /* Chagne file pionter ‘fd’ to next block */ int offset=lseek(fd , bks , SEEK_CUR ); 8 } .... ✌ ✆ File Access Modes The protection and permission codes of a file in Linux OS system are given in the following table. Mode Permission Value Protection Value NONE 0 0 READ 4 1 WRITE 2 2 EXEC 1 4 Permission to a file in Linux OS system for a user, group or system is managed by chmod command. This command accepts the file protection mode in numeric form as given below: ✞ 1 chmod 777 <file or dir > ✌ ✆ In Linux OS system, a file has three levels of discretionary protection and permission. permission to a file in Linux OS system is represented by a string that looks like “Zrwxr- wxrwx”, in which first character, ‘Z’ defined type of directory or file, i.e. ‘d’ for directory, ‘l’ for linked file, ‘s’ for setuid bit, ‘t’ for the sticky bit etc. Next three characters (triads) are protection/permission mode for owner, second is for group and third is for all other users. Character ‘r’, ‘w’ and ‘x’ represents to read, write and execute modes respectively. If user has readonly permission to a file then three characters shall be looked like ‘r – –’ where dashes represent no write and no execute permissions to the user for the given file or directory. The permission code in chmod command, as given above is splited in all possible combinations before defining user’s permission and execution of chmod com- mand. Note that, in permission code ‘777’, first ‘7’ is for owner second ‘7’ is for group and third ‘7’ is for all other users. For example, ‘7’ is splitted in 4+2+1 form to mark a file as read-write-exec. ‘3’ as 0+2+1, i.e. read-write- –. ‘5’ as 4+0+1, i.e. read- – - exec. Permission with ‘–’ means files can not be either read, write or permissioned and directories can not be permissioned with cd command. If there is no valid combinations
  • 31. 1.9. FUNCTION 181 are made from permission code, then invalid mode error is thrown by the system. The permission string can be equivalently computed with binary values as shown below: ✞ 1 -rwxrwxrwx ; permission string 111111111 ; Binary values ✌ ✆ The triad values for owner (let) are computed for read permission as 1002 = 410, for write permission as 0102 = 210, for read-write 1102 = 610 and so on. memset Syntax of memset() function is ✞ void *memset(void *s, int c, size_t n); ✌ ✆ The memset() function converts ‘c’ into unsigned char, then stores the character into the first ‘n’ bytes of memory pointed-by ‘s’. A simple example is ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 /* iniitalized a string */ char str1 [ ] = "These is memset !!!! "; 7 /* memset first six characters of the string*/ memset(str1 , ’-’, 6); 9 puts (str1 ); /* iniitalized a string */ 11 char str2 [ ] = "These is memset !!!! "; /* memset first three characters of the string*/ 13 memset(str2 , ’-’, 3); puts (str2 ); 15 /* iniitalized a string */ char str3 [ ] = "These is memset !!!! "; 17 /* memset first four characters of the string*/ memset(str3 , ’-’, 4); 19 puts (str3 ); return 0; 21 } ✌ ✆ ✞ ------is memset !!!! ---se is memset !!!! ----e is memset !!!! ✌ ✆ memcpy The memcpy() function shall copy n bytes from the object pointed to by ‘source’ into the object pointed to by ‘destination’. If copying takes place between objects that overlap, the behavior is undefined. The function returns ‘destination’. Syntax of the function is
  • 32. 182 Basic C ✞ 1 void *memcpy(void * restrict <destination >, const void * restrict <source >, size_t <n>); ✌ ✆ Because the function does not have to worry about overlap, it can do the simplest copy it can. ✞ #include <stdio.h> 2 #include <string.h> 4 int main () { const char src [50] = "Experimental string."; 6 char dest [50]; 8 printf("Before memcpy destination is : %sn", dest ); memcpy(dest , src , strlen(src) + 1); 10 printf("After memcpy destination is : %sn", dest ); 12 return (0); } ✌ ✆ ✞ Before memcpy destination is : After memcpy destination is : Experimental string. ✌ ✆ memcpy() function is very useful when a user defined function pointer is required to return the local pointer defined inside the function. ✞ #include <stdio.h> 2 char *toLower (char str[ ]) { 4 /* Initiate local string pointer */ char *s = NULL ; 6 /* Allocate memory for local pointer */ s = malloc(sizeof (char )*(1024)); 8 int i = 0; /* Create a local array for storing * 10 * modified string received from * * from function argument . */ 12 char st [1024]; while (str[i] != ’0 ’) { 14 /* Capital letters starts from * * char code 65 to 90. While * 16 * small letters starts from 97* * to 122. A difference of +32 */ 18 if (str[i] >= 65 && str[i] <= 90) { st[i] = str[i] + 32; 20 } else { st[i] = str[i]; 22 } i++; 24 }
  • 33. 1.9. FUNCTION 183 st[i] = ’0’; 26 /* Copy array into memory as a pointer . */ memcpy(s, st , 1024); 28 /* Return function pointer.*/ return s; 30 /* Free allocated memory.*/ free (s); 32 } 34 int main (void ) { char str[ ] = "This iS MY striNg."; 36 printf("Actual string is :"); printf(""%s"n",str); 38 printf("Lower case string is :"); printf(""%s"", toLower (str)); 40 return 0; } ✌ ✆ ✞ Actual string is : "This iS MY striNg ." Lower case string is : "this is my string ." ✌ ✆ memmov The memmove() function shall copy n bytes from the object pointed to by ‘source’ into the object pointed to by ‘dest’. Copying takes place as if the n bytes from the object pointed to by ‘source’ are first copied into a temporary array of n bytes that does not overlap the objects pointed to by ‘dest’ and ‘source’, and then the n bytes from the temporary array are copied into the object pointed to by ‘dest’. The function returns the value of ‘dest’. The easy way to implement this without using a temporary array is to check for a condition that would prevent an ascending copy, and if found, do a descending copy. Unlike the memcpy(), this function guaranteed to move contents from source to destination even if the memory regions pointed by ‘source’ and ‘dest’ overlaps. Its syntax is ✞ void *memmove (void * <dest >, const void *<source >, size_t <n>); ✌ ✆ ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 char str[ ] = "Experimental string"; memmove (str + 10, str + 5, 5); 7 puts (str); return 0; 9 } ✌ ✆ ✞ Experimentimentring ✌ ✆
  • 34. 184 Basic C memchr The memchr() function shall locate the first occurrence of ‘c’ (converted to an unsigned char) in the initial n bytes (each interpreted as unsigned char) of the object pointed to by ‘string’. If ‘c’ is not found, memchr() returns a null pointer. Its syntax is ✞ 1 void *memchr(const void *<string >, int <c>, size_t <n>); ✌ ✆ ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 char * pch; char str[ ] = "Example string"; 7 pch = (char *) memchr(str , ’e’, strlen(str)); if (pch != NULL ) 9 printf("’e’ found at position %d.n", pch - str + 1); else 11 printf("’e’ not found.n"); return 0; 13 } ✌ ✆ ✞ ’e’ found at position 7. ✌ ✆ memcmp The memcmp() function shall compare the first n bytes (each interpreted as unsigned char) of the object pointed to by ‘mem1’ to the first n bytes of the object pointed to by ‘mem2’. The sign of a non-zero return value shall be determined by the sign of the difference between the values of the first pair of bytes (both interpreted as type unsigned char) that differ in the objects being compared. ✞ 1 int memcmp(const void *<mem1 >, const void *<mem2 >, size_t <n>); ✌ ✆ ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 char buff [ ] = "Artificial "; char buff2[ ] = "ARtificial "; 7 int n; 9 n = memcmp(buff , buff2 , sizeof (buff )); 11 if (n > 0) 13 printf(" ’%s’ is greater than ’%s ’.n", buff , buff2); else if (n < 0) 15 printf(" ’%s’ is less than ’%s ’.n", buff , buff2);
  • 35. 1.9. FUNCTION 185 else 17 printf(" ’%s’ is the same as ’%s ’.n", buff , buff2); 19 return 0; } ✌ ✆ ✞ ’Artificial ’ is greater than ’ARtificial ’. ✌ ✆ 1.9.8 Unicode Support C provides unicode support for the native operating systems which have their own unicode support. To set the native local language ✞ 1 char *locale = setlocale (LC_CTYPE , " en_IN.UTF -8"); ✌ ✆ The function setlocale() is defined in the macro “locale.h”. If native locale doesn’t use UTF-8 encoding it need to replace the empty string with a locale like “en IN.UTF-8”. Localisation environment has following parameters ✞ 1 ANG=en_US LC_CTYPE ="en_US" 3 LC_NUMERIC ="en_US" LC_TIME=" en_US" 5 LC_COLLATE ="en_US" LC_MONETARY ="en_US" 7 LC_MESSAGES ="en_US" LC_PAPER ="en_US" 9 LC_NAME=" en_US" LC_ADDRESS ="en_US" 11 LC_TELEPHONE ="en_US" LC_MEASUREMENT ="en_US" 13 LC_IDENTIFICATION ="en_US" LC_ALL= ✌ ✆ User can change any specific environmental parameter by using method given above or setting all environment to locals by setting ‘LC ALL’ as shown below. ✞ char *locale = setlocale (LC_ALL , "en_IN.UTF -8"); ✌ ✆ An example is ✞ 1 #include <stdio.h> #include <wchar.h> 3 #include <stdlib.h> #include <locale.h> 5 int main (void ) { 7 /* If your native locale doesn’t use UTF -8 encoding * * you need to replace the empty string with a *
  • 36. 186 Basic C 9 * locale like "en_US.utf8 " */ char * locale = setlocale (LC_CTYPE , "en_IN.UTF -8"); 11 FILE *in = fopen("a.txt", "r"); 13 wint_t c; while ((c = fgetwc(in)) != WEOF ) 15 putwchar (c); fclose(in); 17 return EXIT_SUCCESS ; 19 } ✌ ✆ 1.10 Procedures & Functions A function is often executed (called) several times, called from different locations, during a single execution of the program. After finishing a subroutine, the program will branch back (return) to the point after the call. A function is like a black box. It takes inputs, does something with them, then spits out an answer. ✞ 1 #include <stdio.h> 3 void P_Loop(void ) { int i; 5 for (i = 1; i <= 5; i++) { printf("%d ", i * i); 7 } } 9 int main (void ) { 11 P_Loop (); printf("n"); 13 P_Loop (); return 0; 15 } ✌ ✆ The output is ✞ 1 4 9 16 25 1 4 9 16 25 ✌ ✆ 1.10.1 Code Optimisation It is very common that in a program, there are excess lines of script or it has time/memory consuming algorithm. Ultimately program takes longer time for execution. By using ad- vance methods of algorithm and script writing we can reduce the size as well as execution time of the program. It is known as code optimization. In other words, code optimization is a method of code modification to improve code quality and efficiency. A program may
  • 37. 1.10. PROCEDURES & FUNCTIONS 187 be optimized so that it becomes a smaller size, consumes less memory, executes more rapidly or performs fewer input/output operations. Illustrated Example Assume that we have to find all the prime numbers within 1 to 20. We write a program in which each number is divided by all numbers less than to it. For example, to check whether 19 is a prime or not, it is divided by integers started from 2 to 19 and if any of the divisor returns the zero as remainder then the number 19 is not prime. ✞ #include <stdio.h> 2 #include <stdlib.h> 4 int main () { int n, i = 1, j, m = 0; 6 printf("Enter Limit of Prime Number : "); scanf("%d", &n); 8 while (i <= n) { int k = 0; 10 for (j = 2; j < i; j++) { if (i % j == 0) {// line to be optimised 12 k++; } 14 } if (k == 0) { 16 m++; printf("%d is a prime number .n", i); 18 } i++; 20 } printf("Total %d primes are found.n", m); 22 return 0; } ✌ ✆ Another concept is that, if a number, ‘n’, is not divisible by a maximum integer value of ‘n/2’ then it is not divisible by any integers larger ‘n/2’. For example if 19 is not divisible by maximum integer value of 19/2, ie 9 then 19 never be completely divisible by 10 or more. By this method we reduce the iteration loops in the program. Above example can be rewritten as ✞ 1 #include <stdio.h> #include <stdlib.h> 3 int main () { 5 int n, i = 1, j, m = 0; printf("Enter Limit of Prime Number : "); 7 scanf("%d", &n); while (i <= n) { 9 int k = 0; for (j = 2; j <= i/2; j++) {// line is optimised 11 if (i % j == 0) { k++;
  • 38. 188 Basic C 13 } } 15 if (k == 0) { m++; 17 printf("%d is a prime number .n", i); } 19 i++; } 21 printf("Total %d primes are found.n", m); return 0; 23 } ✌ ✆ By this way we have reduce the execution time of the program (better performance) without compromising its output. Again if a number ‘n’ is divisible by ‘2’, above program checks the divisibility upto maximum integer value of ‘n/2’ by several iteration even if it was confirm that the number ‘n’ is not prime in first iteration. To enhance the performance of the program, we can again optimize the code by using break-continue function when number is checked and confirmed that it is not prime in first iteration. ✞ 1 #include <stdio.h> #include <stdlib.h> 3 int main () { 5 int n, i = 1, j, m = 0; printf("Enter Limit of Prime Number : "); 7 scanf("%d", &n); while (i <= n) { 9 int k = 0; for (j = 2; j <= i / 2; j++) { 11 if (i % j == 0) { k++; 13 break;/* no further check that the number* *is primeif it is declared not a * 15 *prime in first few iterations . */ }else { 17 continue ; } 19 } if (k == 0) { 21 m++; printf("%d is a prime number .n", i); 23 } i++; 25 } printf("Total %d primes are found.n", m); 27 return 0; } ✌ ✆ It again enhance the performance of program by multiple times. Similarly, if given number is even number then it shall never be prime and if given number is odd number then it shall not be prime if it has a perfect square-root. Again, square-root of odd number is
  • 39. 1.10. PROCEDURES & FUNCTIONS 189 only odd number. It means we have to check the divisibility of given number by all odd numbers less than or equal to square root of the given number. By this way we can further optimize the code for prime numbers. ✞ #include <math .h> 2 #include <stdio.h> 4 int main () { int n = 147853; 6 int x, y = 1; int sq = sqrt (n) + 1; 8 if (n < 2) y = 0; 10 if (n == 2 || n == 3) y = 1; 12 if (n % 2 == 0) y = 0; 14 for (x = 3; x <= sq; x += 2) { if (n % x == 0) 16 y = 0; } 18 if (y == 1) { printf("A primen"); 20 } else { printf("Not A primen"); 22 } return 1; 24 } ✌ ✆ Execution Time In good programming practices, codes are written in such manner that they took least execution time with optimum performance. Using clock() function, we can get the execution time of the program. A simple example is given below. ✞ #include <stdio.h> 2 #include <stdlib.h> #include <time .h> 4 int main () { 6 clock_t startTime = clock(); int n = 1000000 , i = 1; 8 while (i <= n) { i++; 10 } clock_t endTime = clock(); 12 double td = (endTime - startTime ) / (double) CLOCKS_PER_SEC ; printf("Program has run for %5.8 f secondsn", td); 14 return 0; } ✌ ✆ ✞ Program has run for 0.00000200 seconds ✌ ✆
  • 40. 190 Basic C Additional to this, some time it is required to know the local time (computer clock time) for best performance of the program. Here is an example that uses time.h header file to get the local time. The code line ✞ 1 time_t time (time_t *seconds ); ✌ ✆ returns the time lapsed since the mid night of January 1, 1970, measured in seconds. If ‘seconds’ is not NULL, the return value is also stored in variable ‘seconds’. ✞ 1 #include <stdio.h> #include <time .h> 3 int main () { 5 time_t seconds; 7 seconds = time (NULL ); printf("Hours since January 1, 1970 = %ldn", seconds / 3600); 9 return (0); 11 } ✌ ✆ ✞ Hours since January 1, 1970 = 405089 ✌ ✆ Another example is ✞ 1 #include <time .h> #include <stdlib.h> 3 #include <stdio.h> 5 int main (void ) { time_t current_time ; 7 char * c_time_string ; int i = 5; 9 while (i > 0) { sleep (1); 11 /* Obtain current time . */ current_time = time (NULL ); 13 /* Convert to local time format. */ c_time_string = ctime(& current_time ); 15 printf("Current time is %d, %s", current_time , c_time_string ); i--; 17 } return EXIT_SUCCESS ; 19 } ✌ ✆ ✞ Current time is 1458321446 , Fri Mar 18 22:47:26 2016 Current time is 1458321447 , Fri Mar 18 22:47:27 2016 Current time is 1458321448 , Fri Mar 18 22:47:28 2016 Current time is 1458321449 , Fri Mar 18 22:47:29 2016
  • 41. 1.10. PROCEDURES & FUNCTIONS 191 Current time is 1458321450 , Fri Mar 18 22:47:30 2016 ✌ ✆ Specifier Output Format %a Short weekday name %A Full weekday name %b Short month name %B Full month name %c Time stamp %d Day of the month %H Hour in 24h format %I Hour in 12h format %j Day of the year %m Month as a decimal number %M Minutes %p AM or PM %S Seconds %U Week number, first day of first week is Sunday %w Weekday as a decimal number with Sunday as 0 (0-6) %W Week number, first day of first week is Monday %x Date representation %X Time representation %y Two digit Year format (00-99) %Y Four digit Year format %Z Timezone name %% A % sign Table 1.22: Date & time format specifiers. 1.10.2 Increments & Decrements The character set ‘++’ is used to increase the value by one and −− is used to decrease the value by one of the variable with which the character set is prefixed or post-fixed. There are two ways to use these notations. One is ‘++n’ and other is ‘n++’. Both have same meaning but first is used where value is to be used after one increment while later is used where value is to be increase by one after using it.
  • 42. 192 Basic C ✞ 1 #include <stdio.h> #include <stdlib.h> 3 int main (void ) { 5 int i = 0; printf("use of ++i n"); 7 while (i < 3) { /* calling & placing at same place.*/ 9 printf("%d => %d n", i, ++i); } 11 printf("use of i++ n"); int j = 0; 13 while (j < 3) { printf("%d => %d n", j, j++); 15 } return EXIT_SUCCESS ; 17 } ✌ ✆ ✞ use of ++i 1 => 1 2 => 2 3 => 3 use of i++ 1 => 0 2 => 1 3 => 2 ✌ ✆ If increment or decrements is used inside a loop, there are no difference in the use of ‘i++’ or ‘++i’. ✞ #include <stdio.h> 2 #include <stdlib.h> 4 int main (void ) { int i = 0; 6 printf("Use of i++ in while loop n"); while (i < 3) { 8 /* first increment .*/ i++; 10 /* then use.*/ printf(":-> %dn", i); 12 } 14 printf("Use of ++i in while loop n"); int j = 0; 16 while (j < 3) { /* first increment .*/ 18 ++j; /* then use.*/ 20 printf(":-> %dn", j);
  • 43. 1.10. PROCEDURES & FUNCTIONS 193 22 } return EXIT_SUCCESS ; 24 } ✌ ✆ ✞ Use of i++ in while loop :-> 1 :-> 2 :-> 3 Use of ++i in while loop :-> 1 :-> 2 :-> 3 ✌ ✆ This increment operator can not be used in variable initialization or with constants like 3 + + or directly in output stream functions like printf. The following type of syntax are illegal. ✞ int i=2++; // illegal coding 2 printf("Increment of 2 is %dn" ,2++);// illegal coding ✌ ✆ The same methods can be used for decrements operator. In increments or decrements operations, value of variable i is incremented by one and then the result is assigned to variable i. This is why, constant values can not be used with this unary operator, i.e. 5 + + and + + 5 cause compile time errors. See another example for i + + and + + j unary operators. ✞ #include <stdio.h> 2 int main (int argc , char ** argv ) { 4 int i = 0; while (i < 3) { 6 printf("i is %dn", i++);/* started from 0*/ } 8 printf("n"); int j = 0; 10 while (j < 3) { printf("j is %dn", ++j);/* started from 1*/ 12 } return 0; 14 } ✌ ✆ ✞ i is 0 i is 1 i is 2 j is 1 j is 2 j is 3 ✌ ✆
  • 44. 194 Basic C Again, before summing up this section, always remember that k + 1 and k + + results increment of variable ‘k’ by one. But first expression is purely different to second ex- pression. In first expression, the value of ‘k’ remains unchanged only results reflects to increment by one, while in second expression, value of ‘k’ is incremented by one and again assigned to it. ✞ 1 #include <stdio.h> 3 int main (int argc , char ** argv ) { int k = 0, l = 0; 5 printf("k+1 is %d and l++ is %dn", k+1, l++); printf("k+1 is %d and l++ is %dn", k+1, l++); 7 printf("k+1 is %d and l++ is %dn", k+1, l++); return 0; 9 } ✌ ✆ ✞ k+1 is 1 and l++ is 0 k+1 is 1 and l++ is 1 k+1 is 1 and l++ is 2 ✌ ✆ When increment and decrements operators are used simultaneously, then increment and decrements is performed simultaneous in order. ✞ 1 #include <stdio.h> #include <stdlib.h> 3 int myF(int i) { 5 int j = 1, re , r = 2; while (j < i) { 7 re = (r++) *(++ r);//re = (2) * (4); r = 4; j++; 9 } return re; 11 } 13 int main () { int i = 5, j = 3; 15 printf("%d", myF (5)); 17 return 0; } ✌ ✆ ✞ 80 ✌ ✆ In above program, in each loop, first value of r in r++ is used and then it is incremented. The value of r in ++r is incremented and then used. Therefore, in first loop, the equivalent expression shall be ✞ 1 re = (2) * (4); ✌ ✆
  • 45. 1.10. PROCEDURES & FUNCTIONS 195 And for next loop, the new value of r is 4. In case of increment operator is used with array elements like ✞ 1 a[i]=i++; ✌ ✆ In this case, initial value of ‘i’ is taken and incremented by one. This original value is stored as element of array ‘a’, at index position given by incremented ‘i’, i.e. ‘i+1’. Actually, for any value of ‘i’ above expression becomes ✞ 1 a[i+1]= i; ✌ ✆ See the example below ✞ 1 #include <stdio.h> 3 int main (int argc , char *argv []) { int i = 80; 5 int j = i; char a[100]; 7 /*In following expression , first value of i* *is used and then it is incremented . Value* 9 *of i stored at array element as a[i++]= i */ a[i] = i++; 11 /* Actual i and equivalent char */ printf("%d=>%cn", j, j); 13 /* Values stored in array as its* *element for initial i values */ 15 printf("a[%d]=%cn", j, a[j]); /* Actual array element values*/ 17 printf("a[%d]=%cn", i, a[i]); return 0; 19 } ✌ ✆ ✞ 80=>P a[80]=( a[81]=P ✌ ✆ Again see the following example, in which we try to get the result 110 by multiplying increment operators. ✞ 1 #include <stdio.h> 3 int main (int argc , char *argv []) { int i = 10; 5 printf("%dn", i++ * i++); return 0; 7 } ✌ ✆ ✞ 100 ✌ ✆
  • 46. 196 Basic C But actual result is 100 rather than 110. It means after using the current value of ‘i’, ‘i’ does not goes increment for next use of ‘i’. It reason is that, C does not guaranteed to increment the value of ‘i’ just after using it but it increments value of ‘i’ sometime before the expression is considered “finished” or just before the next “sequence point”. 1.10.3 Static Function In a program, if a function is declared as static then it can only be called from the same file in which it is declared. It can not called from the other files. The syntax of static function is ✞ 1 static int compare(int a, int b) { return (a + 4 < b) ? a : b; 3 } ✌ ✆ An example of static function is ✞ 1 #include <stdio.h> 3 static int compare(int a, int b) { return (a > b) ? a : b; 5 } 7 int main () { int j; 9 j = compare (2, 4); printf(":-> %d.n", j); 11 return 0; } ✌ ✆ ✞ :-> 4. ✌ ✆ 1.10.4 Function with Variable Arguments A static function can be called by its prototype. Normally in static functions number of arguments remain fix but variable number of arguments can also be passed to the function. Calling of a function with variable arguments is given in following example. ✞ 1 #include <stdlib.h> 3 #define MAXARGS 3 int var_arg (); 5 int main () { 7 var_arg (1, 2, 3); return 0; 9 } 11 int var_arg (int a) {
  • 47. 1.10. PROCEDURES & FUNCTIONS 197 int i = 0; 13 while (i < MAXARGS) { printf("%d argument is %d.n", i, (&a)[i]); 15 i++; } 17 return a; } ✌ ✆ A ‘var arg’ function is defined in prototype as null variables ✞ int var_arg (); ✌ ✆ This prototype function is defined as single argument list. ✞ 1 int var_arg (int a) ✌ ✆ When function is called with three integer arguments, this argument list is passed to the function definition as a list. ✞ 1 var_arg (1, 2, 3); ✌ ✆ Following line in the program ✞ 1 printf("%d argument is %d.n", i, (&a)[i]); ✌ ✆ prints the each element of the variable list of ‘a’. Second method uses macros defined in the header file <stdarg.h>. ✞ 1 #include <stdio.h> #include <stdarg.h> 3 void varStrings (const char *f, ...) { 5 int max_args = 5; va_list args ; 7 va_start (args , max_args ); printf("%sn", f); 9 while (max_args --) puts (va_arg(args , const char *)); 11 va_end(args ); } 13 int main () { 15 varStrings ("f", "Mary ", "had", "a", "little", "lamb "); return 0; 17 } ✌ ✆ The syntax variable argument function requires at least one fixed argument before the ‘...’. Here ‘va list’ creates memory for the variable list ‘valist’. ‘va start’ function accepts arguments and stores in the variable list ‘valist’ memory. ‘va arg’ function returns the variable value from variable list ‘valist’. ‘va end’ function cleans the memory reserved for valist. In pursuance to standard method of programming, in a function with variable
  • 48. 198 Basic C arguments, first argument/element should be an integer, representing the number of ar- guments to be passed to the function. In following example, sum of integers by passing variable arguments is obtained. ✞ 1 #include <stdarg.h> 3 int sum(int num , ...) { va_list ap; 5 int total = 0; va_start (ap , num); 7 while (num > 0) { total += va_arg(ap , int); 9 num --; } 11 va_end(ap); return total; 13 } 15 int main () { /* First argument determines the number of ** 17 ** following arguments , those shall be used ** ** in the sum function . Here it is 5. */ 19 int a = sum(5, 1, 2, 3, 4, 6); 21 /* First argument determines the number of ** ** following arguments , those shall be used ** 23 ** in the sum function . Here it is 2. */ int b = sum(2, 3, 5, 8); 25 printf("Sums are %d and %dn", a, b); return 0; 27 } ✌ ✆ ✞ Sums are 16 and 8 respectively . ✌ ✆ 1.10.5 Indirect Call of Function In C, the input is considered as string even though input contains the name of inbuilt functions or operators. For example, input “sin(90)” is considered as string which is a group of ‘s’, ‘i’, ‘n’, ‘(’, ‘9’, ‘0’, ‘)’ and NULL characters rather than sine operator on operand ‘90’. Using indirect call of a function, we can execute a function by supplying function name as string input. ✞ 1 #include <stdio.h> #include <stdlib.h> 3 #include <math .h> 5 double Equ1 (double x) { return x; 7 }
  • 49. 1.10. PROCEDURES & FUNCTIONS 199 9 double Equ2 (double x) { return x * x; 11 } 13 double Equ3 (double x) { return log(x); 15 } 17 typedef double (* Eqn)(double); 19 int main () { int i; 21 double ic; 23 const char *EqnNames [3] = { "Equ1 ", "Equ2 ", "Equ3 " 25 }; Eqn FEqu [ ] = {Equ1 , Equ2 , Equ3 }; 27 for (i = 0; i < (sizeof (FEqu ) / sizeof (Eqn)); i++) { 29 ic = (* FEqu [i])(i + 1); printf("Eqn Name = %5s : a=%d : Result=%lfn", 31 EqnNames [i], i + 1, ic); } 33 return 0; } ✌ ✆ ✞ Eqn Name = Equ1 : a=1 : Result =1.000000 Eqn Name = Equ2 : a=2 : Result =4.000000 Eqn Name = Equ3 : a=3 : Result =1.098612 ✌ ✆ 1.10.6 Preprocessor Macros Preprocessors are used to define macros or manifest constants and are included in the header of source file. Preprocessors can be defined separately in a file having extensions ‘.h’ or in the same source file. Some of the useful pre-processors are explained below. Literals The token reserved for the preprocessor is the octothorp, #, and the preprocessor makes three entirely different uses of it. Using, this token we can put the macros within the function. Whitespace before the # is ignored. Next use of # in a macro makes input a string, known as compound literal. See the example below: ✞ 1 #include <stdio.h> #define myMacro (v) printf (#v " : %dn", v); 3 int main () {
  • 50. 200 Basic C 5 myMacro (10 / 5); myMacro (15 / 5); 7 return 0; } ✌ ✆ ✞ 10 / 5 : 2 15 / 5 : 3 ✌ ✆ Tokens Body of a macro is considered as a string of tokens rather than a string of characters. C preprocessor tokens are the separate “words” in the body of a macro definition. They are separated from one another by white spaces. For example, the definition ✞ #define FOUR 2*2 ✌ ✆ has one token-the sequence 2*2, but the definition ✞ 1 #define SIX 2 * 3 ✌ ✆ has three tokens 2, *, and 3. Character, strings and token strings differ from each other. It depends on how how multiple spaces are treated in a macro body. The preprocessor doesn’t make calculations; it just substitutes strings. For example ✞ 1 #include <stdio.h> 3 #define SQUARE(X) X*X 5 int main (void ) { int x = 4; 7 printf("x = %dn", x); printf("SQUARE(x): %d", SQUARE(x)); 9 /* Above statement is equivalent to * 11 * printf (" SQUARE(x): %d", x*x); */ return 0; 13 } ✌ ✆ ✞ x = 4 SQUARE(x): 16 ✌ ✆ In above example value of ‘x’ is passed to predefined function ‘SQUARE(X)’ and the function replaces ‘X’ by ‘x’ as ‘x*x’ and ultimately ‘4*4’. Now the result is ‘16’. If the ‘x’ passed to the function as shown in the given example then ✞ #include <stdio.h> 2 #define SQUARE(X) X*X
  • 51. 1.10. PROCEDURES & FUNCTIONS 201 4 int main (void ) { 6 int x = 2; printf("x = %dn", x); 8 printf("SQUARE(x): %d", SQUARE(x+2)); 10 /* above statement is equivalent to * * printf (" SQUARE(x): %d", x+2*x+2); */ 12 return 0; } ✌ ✆ ✞ x = 2 SQUARE(x): 8 ✌ ✆ Result is ‘8’ rather than predicted as ‘16’. The reason behind it is that when ‘x+2’ is passed to the function ‘SQUARE’, it replaces ‘X*X’ by ‘x+2’ as ‘x+2*x+2’ and it gives the ultimately result ‘2+2*2+2’ that is ‘8’. Again ✞ #include <stdio.h> 2 #define SQUARE(X) X*X 4 int main (void ) { 6 /* Initial declaration of x=2. */ int x = 2; 8 /* x=2 */ 10 printf("x = %dn", x); 12 /* In below line , x in incremented * * by 1and it becomes x=2+1=3 before* 14 * it passes to macro SQUARE(). */ printf("SQUARE(x): %d", SQUARE (++x)); 16 /* Above statement is equivalent to * 18 * printf (" SQUARE(x): %d", ++x*++x);* * Here again x is incremented by 1 * 20 * from its previous declaration * * and it becomes x =3+1=4. */ 22 return 0; } ✌ ✆ ✞ x = 2 SQUARE(x): 16 ✌ ✆ #if, #else, #elif, #endif These are also known as conditionals. The #if checks whether a controlling condition expression evaluates to zero or nonzero, and excludes or includes a block of code respec-
  • 52. 202 Basic C tively. ✞ #if 1 2 /* This block will be included */ #endif 4 #if 0 /* This block will not be included */ 6 #endif ✌ ✆ A simple example is ✞ #include <stdio.h> 2 /* Define row size 80*/ #define RSIZE 80 4 /*If row size is >200 set row size 200 */ #if RSIZE > 200 6 #undef RSIZE #define RSIZE 200 8 /* else if row size is <50 set row size 50*/ #elif RSIZE <50 10 #undef RSIZE #define RSIZE 50 12 /* Else set row size 100 :: it is true */ #else 14 #undef RSIZE #define RSIZE 100 16 #endif int main () { 18 printf("The row size is %d.n", RSIZE); do_A (); 20 return 0; } 22 /* Define row size 201*/ #define RSIZE_B 201 24 /*If row size is >200 set row size 200 :: It is true */ #if RSIZE_B > 200 26 #undef RSIZE_B #define RSIZE_B 200 28 /* else if row size is <50 set row size 50*/ #elif RSIZE_B <50 30 #undef RSIZE_B #define RSIZE_B 50 32 /* Else set row size 1001 */ #else 34 #undef RSIZE_B #define RSIZE_B 100 36 #endif 38 do_A () { 40 printf("The row size is %d.n", RSIZE_B); }
  • 53. 1.10. PROCEDURES & FUNCTIONS 203 ✌ ✆ ✞ The row size is 100. The row size is 200. ✌ ✆ #ifdef & #ifndef The #ifdef is similar to #if, except that the code block following it is selected if a macro name is defined. In this respect, ✞ #ifdef NAME ✌ ✆ is equivalent to ✞ 1 #if defined NAME ✌ ✆ A simple example is ✞ 1 #include <stdio.h> #ifndef __cplusplus 3 #error A C++ compiler is required ! #endif 5 int main () { 7 printf("C++ compiler needed !!!"); return 0; 9 } ✌ ✆ The #ifndef is similar to #ifdef, except that the test is reversed: ✞ 1 #ifndef NAME ✌ ✆ is equivalent to ✞ 1 #if !defined NAME ✌ ✆ A simple example is ✞ 1 #include <stdio.h> #ifndef A 3 #define A 10 #endif 5 int main () { 7 printf(":-> %d.n", A); // printed "10" return 0; 9 } ✌ ✆ ✞ :-> 10. ✌ ✆
  • 54. 204 Basic C #define #define is used to define a preprocessor with known value. The syntax for this prepro- cessor is ✞ 1 #define <identifier > <token -string > ✌ ✆ A program written in C is known as macro. When the computer reads the code, it replaces all instances of a word with the specified expression. #define macro is used for this purpose. ✞ 1 #define PRICE_OF_PEN 5 ✌ ✆ When ever we want to print the price of pen, we use the word PRICE OF PEN instead of the number 5, preprocessor will replace all instances of PRICE OF PEN with 5, which the compiler will interpret as the literal integer 5. The preprocessor performs substitution, that is, PRICE OF PEN is replaced by 5. Increments or decrements operation are not allowed with preprocessor identifier. For example ✞ 1 PRICE_OF_PEN ++ /* equals to 5++*/ /*OR*/ 3 ++ PRICE_OF_PEN /* equals to ++5*/ ✌ ✆ are illegal and not allowed. Because above operation becomes ✞ 1 5++ /*OR*/ 3 ++5 ✌ ✆ and these are illegal in C. It means there is no need for a semicolon. The # and ## operators are used with the #define macro. Using # causes the first argument after the # to be returned as a string in quotes. For example, the function ✞ 1 #define as_string ( s ) # s ✌ ✆ will make the compiler turn this function ✞ 1 puts ( as_string ( Hello World! ) ) ; ✌ ✆ into ✞ 1 puts ( "Hello World!" ); ✌ ✆ ✞ 1 #include <stdio.h> #include <string.h> 3 #define as_string ( s ) # s 5 int main () { puts ( as_string (Hello World !!!!)); 7 return 0; } ✌ ✆
  • 55. 1.10. PROCEDURES & FUNCTIONS 205 ✞ Hello World !!!! ✌ ✆ Symbol ## concatenates what is before the ## with what is after it. After concate- nation, strings becomes tokens. For example, in the following code snippets, function ‘concatenate’ converts two strings passed without double quotes, say x and y into token xy. ✞ 1 #define concatenate ( a, b ) a ## b ... 3 int xy = 10; ... ✌ ✆ When this preprocessor is called from anywhere as shown in the below code line, ✞ printf( "%d", concatenate ( x, y )); ✌ ✆ compiler turns this code line as ✞ 1 printf( "%d", xy); ✌ ✆ which will, of course, display 10 in the standard output. ✞ 1 #include <stdio.h> #include <string.h> 3 #define concatenate ( a, b ) a ## b 5 int main () { int xy = 10; 7 printf("%d", concatenate (x, y)); return 0; 9 } ✌ ✆ ✞ 10 ✌ ✆ It is possible to concatenate a macro argument with a constant prefix or suffix to obtain a valid identifier as in ✞ 1 #define make_function ( name ) int my_ ## name (int foo) {} make_function ( bar ) ✌ ✆ which will define a function called my bar(). But it isn’t possible to integrate a macro argument into a constant string using the concatenation macro. In order to obtain such an effect, one can use the ANSI C property that two or more consecutive string constants are considered equivalent to a single string constant when encountered. Using this property, one can write ✞ #define eat( what ) puts ( "I’m eating " #what " today." ) 2 eat( fruit ) ✌ ✆
  • 56. 206 Basic C which the macro-processor will turn into ✞ puts ( "I’m eating " "fruit" " today." ) ✌ ✆ which in turn will be interpreted by the C parser as a single string constant. The following trick can be used to turn a numeric constants into string literals ✞ 1 #define num2str (x) str(x) #define str(x) #x 3 #define CONST 23 puts (num2str (CONST)); ✌ ✆ This is a bit tricky, since it is expanded in 2 steps. First ‘num2str(CONST)’ is replaced with str(23), which in turn is replaced with “23”. ✞ #include <stdio.h> 2 #include <string.h> #define num2str (x) str(x) 4 #define str(x) #x #define CONST 23 6 int main () { 8 puts ( num2str(CONST)); return 0; 10 } ✌ ✆ ✞ 23 ✌ ✆ Using of catecanation symbol ‘##’ is useful when we have to create different user defined functions with same signature of function which are being called through their pointer addresses. See the example below, in which we have create a function by using ‘##’ symbol. ✞ 1 #include <stdio.h> 3 #define init_fcn (name , type ) /* Create structure for object ‘age’*/ 5 typedef struct { 7 type value; } F## name ; 9 /* Create mf_age function */ inline F## name mf_## name (type v) 11 { F## name t; 13 t.value = v; return t; 15 } 17 int main () { init_fcn (age , int);
  • 57. 1.10. PROCEDURES & FUNCTIONS 207 19 init_fcn (Roll , int); printf("%dn",mf_age (20) ); 21 printf("%dn",mf_Roll (1020)); return 0; 23 } ✌ ✆ ✞ 20 1020 ✌ ✆ A macro assigned with a numerical value using #define preprocessor can be assessed from anywhere in the program. But it can not be assigned new value within the pro- gram. To change the assigned value to a macro, it should be redefined by using #define preprocessor. ✞ #include <stdarg.h> 2 #define MAX_NO 100 4 int main () { printf("Maximum Nos is %d.n", MAX_NO); 6 #define MAX_NO 10 printf("Maximum Nos is %d.n", MAX_NO); 8 MAX_NO =50; // Illegal assignment . Shows error printf("Maximum Nos is %d.n", MAX_NO); 10 return 0; } ✌ ✆ Example for preprocessor #define is given below ✞ 1 #include <stdio.h> #define getmax(a,b) ((a) >(b)?(a):(b)) 3 int main () { 5 int y; y = getmax (5, 2); 7 printf("The max value is %d.", y); return 0; 9 } ✌ ✆ ✞ The max value is 5. ✌ ✆ Use of #define function must be used carefully when the defined value is to be used in mathematical expression. See the example below: ✞ 1 #include <stdio.h> #define PI 3.142857143 /* First form of defining macro.*/ 3 int main () { 5 double i = 2 * PI / 3; printf("i is %lf", i); 7 return 0;
  • 58. 208 Basic C } ✌ ✆ The expression line of above example ✞ double i = 2 * PI / 3; ✌ ✆ The ‘PI’ is replaced by the macro value ‘3.14’ as ✞ 1 double i = 2 * 3.142857143 / 3; ✌ ✆ And the program gives result ✞ i is 2.095238 ✌ ✆ Now, see the example shown below, in which the ‘PI’ macro value is changed in rational form even though its numerical value is same. ✞ 1 #include <stdio.h> 3 #define PI 22 / 7 /* Rational form . */ /*Here , 22/7 is equal to 3 numerically */ 5 int main () { 7 double i = 2 * PI / 3; printf("i is %lf", i); 9 return 0; } ✌ ✆ This form of defining a value is wrong. See the reason in following lines. Assume that, ‘PI’ is defined as shown below ✞ #define PI 22 / 7 ✌ ✆ When preprocessor is replaced by its expression, the expression i becomes as ✞ 1 double i = 2 * PI / 3; ✌ ✆ At the time of compilation, preprocessor value of PI is used as 3 rather than 3.142857143. Now, the value of i becomes ✞ 1 double i = 2 * 3 / 3; ✌ ✆ On solving this expression, the final result thus obtained is 2, which is not what we expected. ✞ i is 2.000000 ✌ ✆ For desired output, proprocessor PI should be defined as (float)22/7 instead of 22/7. See the modified form of above example.
  • 59. 1.10. PROCEDURES & FUNCTIONS 209 ✞ 1 #include <stdio.h> 3 #define PI (float) 22 / 7 5 int main () { double i = 2 * PI / 3; 7 printf("i is %lf", i); return 0; 9 } ✌ ✆ ✞ i is 2.095238 ✌ ✆ The preprocessors may be defined either before or after the header inclusion. In both cases, output is same. ✞ 1 #define NOS 10 3 #include <stdio.h> 5 int main () { printf("%d",NOS); 7 } ✌ ✆ ✞ 10 ✌ ✆ ANSI C defines some useful preprocessor macros and variables, also called “magic con- stants”. ✞ 1 __ FILE __ => The name of the current file , as a string literal. __ LINE __ => Current line of the source file , as a numeric literal . 3 __ DATE __ => Current system date , as a string. __ TIME __ => Current system time , as a string. 5 __ TIMESTAMP __ => Date and time (non - standard ). __ cplusplus => undefined when your C code is being compiled by a C compiler . 7 __ func __ => Current function name of the source file , as a string. ✌ ✆ A simple example for using of preprocessors is derived in three parts. Main part, sum part and preprocessors for sum part. Following is the code of ‘sum.h’ preprocessor ✞ 1 #ifndef SUM_H #define SUM_H 3 #ifdef __cplusplus extern "C" { 5 #endif /* function identifier for sum_f() defined in sum.c*/ 7 int sum_f(int a, int b); #ifdef __cplusplus 9 }
  • 60. 210 Basic C #endif 11 #endif /* SUM_H */ ✌ ✆ Codes of sum function is define in the file ‘sum.c’. ✞ 1 /* sum_f() function for adding two numbers */ int sum_f(int a, int b) { 3 int c; c = a + b; 5 return c; } ✌ ✆ Main function for calling a procedure is defined in ‘main.c’ file as ✞ #include <stdio.h> 2 /* sum.h header contains sum_f() function * * that should be indentified and called. */ 4 #include "sum.h" 6 int main (void ){ int a=2,b=3; 8 /* sum_f() function is called from * *sum.c and identified via sum.h */ 10 int c=sum_f(a,b); printf("The sum of 2 and 3 is %d.",c); 12 return 0; } ✌ ✆ When program is compiled and run the output is ✞ The sum of 2 and 3 is 5. ✌ ✆ If a macro produces multiple statements, or declares variables, it can be wrapped in a do { ... } while(0) loop, with no terminating semicolon. This allows the macro to be used like a single statement in any location. ✞ 1 #define FREE (p) free (p); p = NULL ; /* Bad practice .*/ #define FREE (p) do { free (p); p = NULL ; } while(0) /* Good practice .*/ ✌ ✆ 1.10.7 Type Converter Following is an example of string to integer conversion. ✞ #include <stdio.h> 2 #include <string.h> 4 int main (int argc , char *argv [ ]) { char st [10] = "This "; 6 printf("String ’%s’ = integer %d.n", st , (int) st);
  • 61. 1.11. PARSING ARGUMENTS 211 return 0; 8 } ✌ ✆ ✞ String ’This ’ = integer 2280640. ✌ ✆ 1.11 Parsing Arguments When a program is being executed via another program internally, arguments are required to be passed to the executable ie the program. These arguments are considered as inputs for the executable. To pass the values we define main() function as ✞ 1 int main (int argc , char *argv [ ]) ✌ ✆ Here argc counts the number of arguments in an array and argv assigns the values to each respective counter. ✞ 1 #include <stdio.h> #include <string.h> 3 #include <stdlib.h> 5 /* main function is modified according to* *receive the arguments in command line */ 7 int main (int argc , char *argv [ ]) { int argnum = 0; 9 /* Starting from zero */ while (argc > ++ argnum) 11 printf("Argument %d of arguments %d is %c.n", argnum , 13 argc , *argv [argnum ]); 15 exit ( EXIT_SUCCESS ); } ✌ ✆ After compiling and executing the executable as ✞ executable .exe a b c ✌ ✆ Output is ✞ Argument 1 of supplied four arguments is a. Argument 2 of supplied four arguments is b. Argument 3 of supplied four arguments is c. ✌ ✆ Here executable.exe in command-line is also considered as an argument. This is why there are four arguments and first argument, ie 0th argument, is executable.exe itself and rest of the arguments are a, b and c respectively. An other example is given below
  • 62. 212 Basic C ✞ 1 #include <stdio.h> 3 int main (int argc , char ** argv ) { size_t i; 5 for (i = 0; i < argc ; i++) { 7 /* get all the arguments as options * *and initialize option pointer . */ 9 char const *option = argv [i]; /* Get first character of an option argument */ 11 if (option [0] == ’-’) { /*If first character of an option argument * 13 *is ’-’, then following character is a flag */ printf("Flagged option.n"); 15 /* get the second character of an option argument .*/ switch (option [1]) { 17 /*If second char of an option argument * *is ’e’, then print encryption */ 19 case ’e’: printf("You have chosen %c:ENCryption . n", option [1]) ; 21 break; /*If second char of an option argument * 23 *is ’d’, then print decryption */ case ’d’: 25 printf("You have chosen %c:DECryption . n", option [1]) ; break; 27 /*If second char of an option argument * *is ’f’, then print filename */ 29 case ’f’: printf("Your have chosen file name %c.n", option [1]) ; 31 break; /* other wise */ 33 default : printf("I can not understand your option %sn", option); 35 break; } 37 } else { printf("No Flagged Options .n"); 39 } } 41 return 0; } ✌ ✆ When above example is compiled and executed like ✞ executable .exe -e -f ✌ ✆
  • 63. 1.11. PARSING ARGUMENTS 213 The output at console is ✞ No Flagged Option. Flagged Option. You have chosen e:ENCryption . Flagged Option. You have chosen filename f. ✌ ✆ The first output “No Flagged Option” is appeared at the console at first as ‘exe- cutable.exe’ is considered as first parsing argument and it is not prefixed with ‘–’. Using array and pointer we do reverse to a parsed string via command line is given below. ✞ 1 #include <stdio.h> #include <stdlib.h> 3 /* String Length*/ #define SLen 4 5 int main (int argc , char *argv [ ]) { 7 /* Get the commandline string*/ char *name = argv [1]; 9 char nameR [10]; int i; 11 for (i = 0; i < SLen ; i++) /* Store each character of string in array*/ 13 nameR[i] = name [i]; 15 for (i = 4; i > 0; --i) /* Print each character of stored string in array*/ 17 printf("%c", nameR[i - 1]); exit ( EXIT_SUCCESS ); 19 } ✌ ✆ Similarly the string length of given string can also be obtain by using following example ✞ 1 #include <stdio.h> 3 int main (int argc , char *argv [ ]) { if (argv [1] == NULL ) { 5 printf("Use <utility .exe > <string in quote or double quote >.n"); exit (0); 7 } /* Get the commandline string*/ 9 char *name = argv [1]; int i = 0; 11 while (name [i] != NULL ) i++; 13 printf("The length of string is %d", i); return 0; 15 } ✌ ✆
  • 64. 214 Basic C 1.11.1 Array To Integer atoi() function is used to convert an array into integer. This function is very useful for the conversion of number arguments passed as array or pointer into integer value. The use of syntax is explained in the following example. ✞ 1 #include <stdio.h> #include <stdlib.h> 3 int main (int argc , char *argv [ ]) { 5 if (argv [1] == NULL ) { printf("Use <utility .exe > <string >.n"); 7 exit (0); } 9 int i; i = atoi (argv [1]) ; 11 printf("Array to integer is %d.", i); exit ( EXIT_SUCCESS ); 13 } ✌ ✆ Without atoi(), we can also convert an array into integer by using simple mathematics as explained in the following example. ✞ 1 #include <stdio.h> 3 int main () { char intg [ ] = "1234 "; 5 int i = 0, res = 0; /* Here res must be initialized . Otherwise * 7 *product of res and 10 shall be null value*/ while (intg [i] != ’0’) { 9 /* Product of res with 10. res must not be null .* * (intg [i] % 48) is used to convert integer * 11 * charcode into integer value. Charcode of 0 is* * 48. Similarly , charcode of 1 is 49 and so on */ 13 res = res * 10 + (intg [i] % 48); i++; 15 } printf("%dn", res); 17 return 0; } ✌ ✆ ✞ 1234 ✌ ✆ We can also used pointers for array to integer conversion. Above example is modified as it is given below: ✞ 1 #include <stdio.h> 3 int main () { char *intg = "1234 ";
  • 65. 1.12. MATHEMATIS 215 5 int i = 0, res = 0; /* Here res must be initialized . Otherwise * 7 *product of res and 10 shall be null value*/ while (* intg != ’0 ’) { 9 /* Product of res with 10. res must not be null .* * (intg [i] % 48) is used to convert integer * 11 * charcode into integer value. Charcode of 0 is* * 48. Similarly , charcode of 1 is 49 and so on */ 13 res = res * 10 + (* intg % 48); intg ++; 15 } printf("%dn", res); 17 return 0; } ✌ ✆ atoi() function is used to convert an integer array into integer value. Integer value “1234” as string is stored in memory as a group of characters. Each character is one byte long. 1 2 3 4 i : Value at byte : 00000001 00000010 00000011 00000100 Integer value “1234” in numeric form is stored in 4 bytes long memory space, allocated for solely storing of integer. i : Num value : 00000000 00000000 00000100 11010010 1234 1.12 Mathematis In C programming addition, subtraction, multiplication and division mathematical op- erators can be directly used. Modulus is another mathematical operators that gives the remainder value. Application of these operators are a + b, a − b, a ∗ b, a/b and a%b respectively. ✞ #include <stdio.h> 2 #include <string.h> int a, b; 4 int main (void ) { 6 int a = 5; int b = 2; 8 int add = a + b; int sub = a - b; 10 int mul = a*b; int div = a / b; 12 int mod = a % b;
  • 66. 216 Basic C printf("Addition of %d and %d is : %d n", a, b, add); 14 printf("Subtraction of %d and %d is : %d n", a, b, sub); printf("Multiplication of %d and %d is : %d n", a, b, mul); 16 printf("Division of %d and %d is : %d n", a, b, div); printf("Modulus of %d and %d is : %d n", a, b, mod); 18 return 0; } ✌ ✆ Output of above program is ✞ Addition of 5 and 2 is : 7 Subtraction of 5 and 2 is : 3 Multiplication of 5 and 2 is : 10 Division of 5 and 2 is : 2 Modulus of 5 and 2 is : 1 ✌ ✆ A pointer can also be used in the addition, subtraction, multiplication and division of two or more numbers. ✞ 1 #include <stdio.h> 3 func (int *i, int*j) { *i = *i * *i; 5 *j = *j* *j; } 7 main () { 9 int i = 5, j = 2; func (&i, &j); 11 printf("%d %d", i, j); return 0; 13 } ✌ ✆ ✞ 25, 4 ✌ ✆ 1.12.1 Trigonometric Functions “math.h” preprocessor file provides the mathematical functions that can be used directly in the program. Some of them are defined in following sections. cos, sin & tan The cos, sin, and tan functions return the cosine, sine, and tangent of the argument, expressed in radians. The domain of arguments of sin, cos and tan are [−π/2, π/2], [0, π] and [−π/2, π/2] respectively. The numerical range of sin, cos and tan are [−1, 1], [−1, 1] and [−∞, ∞]. ✞ 1 #include <math .h> double cos(double x);
  • 67. 1.12. MATHEMATIS 217 3 double sin(double x); double tan(double x); ✌ ✆ A simple example is ✞ #include <stdio.h> 2 #include <math .h> 4 int main (void ) { printf("Cosine at 22/7 radian is : %f n", cos (22/7)); 6 printf("Sine at 22/7 radian is : %f n", sin (22/7)); printf("Tangent at 22/7 radian is : %f n", tan (22/7)); 8 return 0; } ✌ ✆ ✞ Cosine at 22/7 radian is : -0.989992 Sine at 22/7 radian is : 0.141120 Tangent at 22/7 radian is : -0.142547 ✌ ✆ Solved Problem 1.8 A right angle triangle having base 20cm and height h. The angle of triangle facing to side h is 30◦ , then find the height of the triangle. Solution We know that in right angle triangle, one angle is 90◦ . If angle facing to the side of hcm is 30◦ then tan 30◦ = h b = h 20 It gives, the height of the triangle h = 20/ √ 3cm. ✞ 1 #include <stdio.h> #include <math .h> 3 #define PI 3.14 5 double DtoR (int x) { return x * PI / 180; 7 } 9 int main () { double h; 11 double b = 20.0; int th = 30; /*in degree */ 13 h = b * tan(DtoR (th)); printf("The height of the triangle is %lf", h); 15 return 0; } ✌ ✆ ✞ The height of the triangle is 11.539928 ✌ ✆
  • 68. 218 Basic C acos, asin & atan The acos() functions return the arccosine of their arguments in radians, and the asin() functions return the arcsine of their arguments in radians. All functions expect the argument in the range [−1, +1]. The arccosine returns a value in the range [0, π]; the arcsine returns a value in the range h − π 2 , π 2 i . The atan() returns their argument value in radian in the range h − π 2 , π 2 i . Method of use of inverse function in following systems. ✞ 1 #include <math .h> double asin (double x); 3 double acos (double x); double atan (double x); ✌ ✆ A simple example is ✞ #include <stdio.h> 2 #include <math .h> 4 int main (void ) { printf("Arc cosine at argument 0.5 is : %f n", acos (0.5)); 6 printf("Arc sine at argument 0.5 is : %f n", asin (0.5)); printf("Arc tangent at argument 1.5 is : %f n", atan (1.5)); 8 return 0; } ✌ ✆ ✞ Arc cosine at argument 0.5 is : 1.047198 Arc sine at argument 0.5 is : 0.523599 Arc tangent at argument 1.5 is : 0.982794 ✌ ✆ cosh, sinh & tanh The cosh(), sinh() and tanh() functions compute the hyperbolic cosine, the hyperbolic sine and the hyperbolic tangent of the argument respectively. ✞ 1 #include <math .h> double cosh (double x); 3 double sinh (double x); double tanh (double x); ✌ ✆ A simple example is ✞ #include <stdio.h> 2 #include <math .h> 4 int main (void ) { printf("Hyperbolic cosine of 0.5 is : %f n", cosh (0.5)); 6 printf("Hyperbolic sine of 0.5 is : %f n", sinh (0.5)); printf("Hyperbolic tangent of 1.5 is : %f n", tanh (1.5)); 8 return 0;
  • 69. 1.12. MATHEMATIS 219 } ✌ ✆ ✞ Hyperbolic cosine at argument 0.5 is : 1.127626 Hyperbolic sine at argument 0.5 is : 0.521095 Hyperbolic tangent at argument 1.5 is : 0.905148 ✌ ✆ acosh, asinh & atanh The acosh() functions compute the inverse hyperbolic cosine of the argument. A domain error occurs for arguments less than 1. The asinh() and atanh() functions compute the inverse hyperbolic sine and inverse hyperbolic tangent of the argument respectively. ✞ 1 #include <math .h> double acosh(double x); 3 double asinh(double x); double atanh(double x); ✌ ✆ A simple example is ✞ #include <stdio.h> 2 #include <math .h> 4 int main (void ) { printf("Hyp inverse cosine of 0.5 is : %f n", acosh (0.5)); 6 printf("Hyp inverse sine of 0.5 is : %f n", asinh (0.5)); printf("Hyp inverse tangent of 1.5 is : %f n", atanh (1.5)); 8 return 0; } ✌ ✆ ✞ Hyperbolic inverse cosine at argument 0.5 is : nan Hyperbolic inverse sine at argument 0.5 is : 0.481212 Hyperbolic inverse tangent at argument 1.5 is : nan ✌ ✆ 1.12.2 Logarithm Function Exponential & Logarithm exp() represents the exponential of a value x with base ‘e’. log() represents the logarithm of a value in natural base ‘e’. ✞ 1 #include <math .h> double exp(double x); 3 double log(double x); ✌ ✆ A simple example is
  • 70. 220 Basic C ✞ 1 #include <stdio.h> #include <math .h> 3 int main (void ) { 5 printf("Exponential of 0.5 is : %f n", exp (0.5)); printf("logarithm of 0.5 at base 10 is : %f n", log (0.5)); 7 return 0; } ✌ ✆ ✞ Exponential of 0.5 is : 1.648721 logarithm of 0.5 at base 10 is : -0.693147 ✌ ✆ 1.12.3 Arithmetic Function In C, symbol ˆ does not represent to power but presents to XOR bitwise operation. In ‘math.h’ preprocessor provides the power operation via pow() function. Power pow() accepts two values. First is base, (b) and second is exponent, (e). Mathematically this function is equivalent to Y = be This function is used as ✞ double pow(double x, double y); ✌ ✆ A table consisting cube of first 10 integers ranging from 1 to 10 is shown below. The formula used is y = i3 Here, 3 is exponent or power and i is base. Base Exp Result, y 1 3 1 2 3 8 3 3 27 4 3 64 5 3 125 6 3 216 7 3 343 8 3 512 9 3 729
  • 71. 1.12. MATHEMATIS 221 A simple example is ✞ 1 #include <stdio.h> #include <math .h> 3 int main (void ) { 5 printf("Power of 2 on base 3 is : %f n", pow(3, 2)); return 0; 7 } ✌ ✆ ✞ Power of 2 on base 3 is : 9.000000 ✌ ✆ Square Root sqrt() returns the square root of a given value. Mathematically it is represented as y = √ i Where, i is any number. The syntax of this function is given below: ✞ 1 double sqrt (double x); ✌ ✆ A table consisting square root of few specific numbers is given below. The formula used is y = √ i Integer Squre Root, y 1 1.00 2 1.41 3 1.73 4 2.00 5 2.24 6 2.45 7 2.65 8 2.83 9 3.00 A simple example is ✞ 1 #include <stdio.h> #include <math .h> 3
  • 72. 222 Basic C int main (void ) { 5 printf("Square root of 1.45 is : %f n", sqrt (1.45)); return 0; 7 } ✌ ✆ ✞ Square root of 1.45 is : 1.204159 ✌ ✆ Floor floor() function accepts a real number. Result of floor value of a real number is, either perfect integer positive or negative as the case may be which is either equal to or less than the given number. Its syntax is given by ✞ 1 double floor(double x); ✌ ✆ -3 -2 -1 0 1 2 3 b −1.5 bc floor(−1.5) b 1.5 bc floor(1.5) A table consisting few positive and negative numbers with their corresponding floor value, is given below. Real Number floor(r) -2.25 -3.00 -2.75 -3.00 -3.00 -3.00 2.25 2.00 2.75 2.00 3.00 3.00 A simple example is ✞ 1 #include <stdio.h> #include <math .h> 3 int main (void ) { 5 printf("Floor of 1.45 is : %f n", floor (1.45)); printf("Floor of -1.45 is : %f n", floor( -1.45) ); 7 return 0; } ✌ ✆
  • 73. 1.12. MATHEMATIS 223 ✞ Floor of 1.45 is : 1.000000 Floor of -1.45 is : -2.000000 ✌ ✆ Ceiling ceil() function accepts a real number. Result of ceiling value of a real number is the perfect integer, either positive or negative as the case may be, which is either equal to or greater than the given number. ✞ double ceil (double x); ✌ ✆ -3 -2 -1 0 1 2 3 b −1.5 bc floor(−1.5) bc ceil(−1.5) -3 -2 -1 0 1 2 3 b 1.5 bc floor(1.5) bc ceil(1.5) A table consisting few positive and negative numbers with their corresponding ceiling value, is given below. Real Number ceil(r) -2.25 -2.00 -2.75 -2.00 -3.00 -3.00 2.25 3.00 2.75 3.00 3.00 3.00 A simple example is ✞ 1 #include <stdio.h> #include <math .h> 3 int main (void ) { 5 printf("Ceil of 1.4855 is : %f n", ceil (1.4855) ); printf("Ceil of -1.4855 is : %f n", ceil ( -1.4855) ); 7 return 0; } ✌ ✆
  • 74. 224 Basic C ✞ Ceil of 1.4855 is : 2.000000 Ceil of -1.4855 is : -1.000000 ✌ ✆ Rounds Off round() function rounds off a fraction number to its nearest perfect integer. The fractional part about which number is rounded-off is 0.5. This definition is advanced with following rules. 1. If non-significant digit is less than 5 and is to be rounded off, the previous digit does not change and non-significant digit is simply dropped. For example 2.301 is significant upto the second place of the decimal then digit 1 is simply dropped and number is rounded off to 2.30. Similarly 2.304 is rounded off upto two place of decimal as 2.30. 2. If non-significant digit is greater than 5 and is to be rounded off, the previous digit (left side digit) is raised by 1 and non-significant digit is dropped. For example 2.306 is significant upto the second place of the decimal then digit 6 is simply dropped and previous digit (left side digit) 0 is raised by 1 and number is rounded off to 2.31. 3. If the rounding off digit is greater than 5, rounding off digit is simply dropped when the previous digit (left side digit) is even. For example, when 2.3546 is rounded off, result is 2.354. 4. If the rounding off digit is greater than 5, rounding off digit is dropped and previous digit (left side digit) is raised by 1 when the previous digit (left side digit) is odd. For example, when 2.3576 is rounded off, result is 2.358. 5. In mathematics and specially in pure science, the large numbers are mostly written in scientific notation form. Hence these numbers are rounded-off upto significant digits. To round-off a large number upto n digits, the rounding-off process is always started from leftmost non-zero digit. For example start process from 2 in 2500 and from 3 in 0.0325. 6. Keep n significant digits and replace rest of digits with zeros. 7. Write number in scientific notation, i.e. a × 10±b form, where a and b are real and significant numbers. 8. Round off mantissa upto the last significant digit. For example 0.2336 can be written as 2.336 × 10−1 in scientific notation and if there are only three significant digits then third significant digit becomes 4 and number becomes 2.34 × 10−1 . Rest of digits are dropped. The syntax of this function is given below: ✞ double round(double x); ✌ ✆
  • 75. 1.12. MATHEMATIS 225 round() function in math library of C is loosely based on the basic rule of round-off. Hence in each case, if rounding-off digit is equal to or larger than 5, then previous digit is raised by 1. A simple example is ✞ 1 #include <stdio.h> #include <math .h> 3 int main (void ) { 5 printf("Rounding of 1.4 is : %f n", round (1.4)); printf("Rounding of 1.6 is : %f n", round (1.6)); 7 return 0; } ✌ ✆ ✞ Rounding of 1.4 is : 1.000000 Rounding of 1.6 is : 2.000000 ✌ ✆ 0 1 2 3 b 1.6 bc round(1.6) b 1.4 bc round(1.4) Round off negative numbers in C program is given below: ✞ #include <stdio.h> 2 #include <math .h> 4 int main (void ) { printf("Rounding of -1.4 is : %f n", round( -1.4)); 6 printf("Rounding of -1.6 is : %f n", round( -1.6)); return 0; 8 } ✌ ✆ ✞ Rounding of -1.4 is : -1.000000 Rounding of -1.6 is : -2.000000 ✌ ✆ -3 -2 -1 0 b −1.6 bc round(−1.6) b −1.4 bc round(−1.4) Rounding off a number cause rounding off errors. For example a real number 2.56889 is actual real number is which is rounded off upto 4th decimal place. It becomes 2.5689. Now the difference of the two values is 2.56889 − 2.5689 = −0.00001. It is error arises due to rounding off a real number.
  • 76. 226 Basic C 1.12.4 Float Point Arithmetic A float or a double has three components, (i) a sign bit, (ii) exponent and (iii) mantissa. A floating point number is written as f = ±m × b±e Here, m is mantissa of the number, b is base, i.e. 2 in IEEE-754 standards. e is exponent of the floating point number. In this section we shall use single point (float) floating numbers. A float data type number is 32 bits long and has three components, (i) a sign bit (first bit from left side), (ii) an exponent (next 8 bits from left side) and (iii) a mantissa (rest of 23 bits). The exponent is an excess-127 binary notation. This binary number is also known as exponent bias. Binary Equivalent Desired Exponent · · · · · · 01111100 -3 01111101 -2 01111110 -1 01111111 0 10000000 1 10000001 2 10000010 3 · · · · · · In this notation, binary number 01111111, equivalent to decimal 127 is a binary ex- ponent equivalent to decimal 0. The next binary exponent i.e. sum of binary 01111111 and bit 1 represents to exponent equivalent to decimal 1 (equivalent to binary 10000000). Similarly, subtraction of bit 1 from 01111111 represents to exponent equivalent to deci- mal −1 (equivalent to binary 01111110). Remember that for binary equivalent form of floating point numbers, base is 2, i.e. exponent binary 01111111 is equal to in decimal form of 20 , exponent binary 10000000 means 21 , exponent binary 01111110 means 2−1 and so on. 125 126 127 128 129 01111101 01111110 01111111 10000000 10000001 −2 −1 0 1 2 2−2 2−1 20 21 22 Decimals Excess-127 e-Line 2e Value
  • 77. 1.12. MATHEMATIS 227 The decimal exponent equivalent to binary exponent is obtained by subtracting 01111111 from the given binary exponent. The mantissa binary numbers are solved from left side to right side. Here, we are dealing with binary fractions, so the leftmost mantissa bit means 2−1 , the next right bit has meaning of 2−2 and so on. The place values of mantissa bits from left side to right side are 2−1 , 2−2 , 2−3 etc. The first bit of a non-zero binary significant is always 1. Hence mantissa in fractions is given by M = 1 + n X i=1 biti × 2−i Here, i is ith bit counted from left hand side to right hand side in mantissa part. n is total number of significant digits in mantissa. Illustrated Example Assume a floating point representation ‘0 0111 1100 0000 0000 0000 0000 0000 000’ shown in binary form. The sign bit of this binary number is ‘0’, hence it is positive value. The exponent binary number is 01111100 and mantissa number is 0000 0000 0000 0000 0000 000. Note that if left most digit of the binary exponent part of floating point number is ‘0’, then exponent is obtained by subtracting 01111111 from the given binary exponent. Here, binary subtraction of 01111100 -01111111 -00000011 which is equivalent to decimal −3. The exponent value is −3. The mantissa part is all zero, hence M = 1 + 23 X i=1 biti × 2−i gives mantissa ‘1’. Now, the number is r = 1 × 2−3 It gives 0.125. Illustrated Example Assume a floating point representation ‘0 1010 0110 1101 0001 1010 1001 0100 101’ shown in binary form. The sign bit of this binary number is ‘0’, hence it is positive value. The exponent binary number is 10100110 and mantissa number is 1101 0001 1010 1001 0100 101. Note that, if the left most digit is of binary exponent is ‘1’, then exponent is obtained by subtracting 01111111 from the given binary exponent. Here, binary subtraction of 10100110 -01111111 00100111
  • 78. 228 Basic C which is equivalent to decimal 39. The exponent value is 39. The mantissa part is M = 1 + 23 X n bitn × 2−n gives mantissa ‘1.818989396095270’. Now, the number is r = 1.818989396095270 × 239 It gives 999999995904. Numerical programming languages use double type floating point mathematics. Therefore each number is denoted as float point, i.e. 1.0 as 1.000000, 0.5 as 0.500000. Sometime, even zero is represented as 2.5×10−18 or as 13.2×10−19 etc. where these values are very very small and are close to zero. Here zero is taken as comparative value rather than absolute value. For example, sometimes, in numerical calculations, identity matrix is represented as
  • 85. 1 3.5 × 10−12 35 × 10−12 1
  • 92. Operators in Float Points Arithmetic Normally, all the arithmetic operators may be used in floating point arithmetic. In float point arithmetic, mixing of two different floating points are allowed. A float or double data type value can be used with int data type value. The result of mixed data type values is extended to match the precision of the more precise data type value. Floating point division does not discard the fractional part and produce round off errors. ✞ #include <stdio.h> 2 int main (void ) { 4 printf("2 + 2.0 is %fn", 2 + 2.0) ; printf("2 - 2.0 is %fn", 2 - 2.0) ; 6 printf("2 / 2.0 is %fn", 2 / 2.0) ; printf("2 * 2.0 is %fn", 2 * 2.0) ; 8 return 0; } ✌ ✆ ✞ 2 + 2.0 is 4.000000 2 - 2.0 is 0.000000 2 / 2.0 is 1.000000 2 * 2.0 is 4.000000 ✌ ✆ Few operators do not work with floating-point datatypes., i.e. real numbers. These are % (modulo) and all of the bitwise operators, like ∼, <<, >>, &, ˆ, and |. ✞ #include <stdio.h> 2 int main (void ) {
  • 93. 1.12. MATHEMATIS 229 4 /* Will show errors*/ printf("2 % 2.0 is %fn", 2 % 2.0) ; 6 /* Will show errors*/ printf("2 ^ 2.0 is %fn", 2 ^ 2.0) ; 8 return 0; } ✌ ✆ An int data type value can be converted into floating point type by casting it. ✞ 1 #include <stdio.h> 3 int main (void ) { printf("2 is %fn", (float) 2); 5 printf("2 is %lfn", (double) 2); return 0; 7 } ✌ ✆ ✞ 2 is 2.000000 2 is 2.000000 ✌ ✆ Few of the floating values are shown in the following table. Float Decimal Binary Form 0 0 0 00000000 00000000000000000000000 -0 -0 1 00000000 00000000000000000000000 0.1 0.10000000149011612 0 01111011 10011001100110011001101 0.125 0.125 0 01111100 00000000000000000000000 0.25 0.25 0 01111101 00000000000000000000000 1 1 0 01111111 00000000000000000000000 2 2 0 10000000 00000000000000000000000 1e+12 999999995904 0 10100110 11010001101010010100101 inf inf 0 11111111 00000000000000000000000 -inf -inf 1 11111111 00000000000000000000000 nan nan 0 11111111 10000000000000000000000 A value is said to be positive infinity (0×7f800000) when its sign bit is 0 and exponent is 0×ff and all mantissa bits are 0. Similarly, a value is said to be negative infinity (0×ff800000) when its sign bit is 1 and exponent is 0×ff and all mantissa bits are 0. A not-a-number (0×7fc00000) case arises when sign bit of floating point number is 0, exponent is 0×ff and mantissa is 0×400000.
  • 94. 230 Basic C Astray Result Sometimes when a float data type number is printed in output console, it gives strange result. Like 3.1 prints as 3.0999999. Its reason is that most hardware uses base 2 for floating-point numbers rather than base 10. All the fractions in base 10 (decimal form) can not be represented in base 2 (binary form). This is why, decimal fraction 3.1 sometimes printed as 3.0999999. Double Floating Point A double is 64 bits long and has three components, (i) a sign bit (first bit from left side), (ii) exponent (next 11 bits from left side) and (iii) mantissa (rest of 52 bits). A double point floating point number is written as f = ±m × b±e Here, m is mantissa of the number, b is base either ‘10’ or ‘e’ or ‘2’ and n is exponent of the floating type number. In computers, the base is ‘2’. Binary number 1111111111 equivalent to decimal 1023 is used as Exponent bias. 1.12.5 Zero Crossing A function is said to be zero-crossing function if its sign changes when its independent variable crosses to zero in a number line. For example f(x) = x; for − 1 < x < 1 changes its sign when x crosses to zero. Similarly f(x) = sin(x); for − 4 < x < 4 is also a zero crossing function which changes its sign when x crosses to zero. Zero crossing has emmence importance in electrical and computer science. Limit At Zero In mathematics, limit is a finite value of a continuous function at a given point. It is represented as lim x→a f(x) = k Where k is fininte value of the function at given point ‘a’. If ‘a’ is zero then some functions behave strangly and do not give finite value, i.e. converging value at the point of limit. Assume a function, here y = sin(x), which converges to a finite value at point ‘0’ lim x→0 y = lim x→0 sin(x) = 0 x y b (0, 0)
  • 95. 1.12. MATHEMATIS 231 Contrast to these types of functions, fraction functions diverge to ∞ when x → 0. See the following limit equation for function y = 1/x, lim x→0 y = lim x→0 1 x = ∞ Now, it is not possible to use this function with other functions in mathematical op- erations. To avoid it, we take approaching limit to point ‘0’ of the function as given below: lim x→0 y = lim x→0 1 x = ∞; when [−∞, 0) < x < (0, ∞] x y b (0, 0) Here, ±∞ is acceptable as 1/ ± ∞ = 0, which is a finite value. 1.12.6 Random Number Generator Following C program is used to generate random numbers. A user defined seed control the initial random number and subsequent random numbers are used as seed for next random number. This program given first five random number against a seed value. ✞ #include <stdio.h> 2 extern void SeedToNew (unsigned int x); extern int MyRand(void ); 4 int main (void ) { 6 int count; unsigned seed ; 8 printf("Please enter seed .n"); while (scanf("%u", &seed ) == 1) { 10 SeedToNew (seed ); for (count = 0; count < 5; count ++) 12 printf("%hdn", MyRand()); printf("Please enter newSeed (q to quit ):n"); 14 } printf("Done n"); 16 return 0; } 18
  • 96. 232 Array & Pointer static unsigned long int newSeed = 1; /* the seed */ 20 int MyRand(void ) { 22 newSeed = newSeed * 1103515245 + 12345; return (unsigned int) (newSeed / 65536) % 32768; 24 } 26 void SeedToNew (unsigned int seed ) { newSeed = seed ; 28 } ✌ ✆ In the codes in line ✞ return (unsigned int) ( newSeed / 65536) % 32768; ✌ ✆ The value 32768 is used to control the limits of the random number. If it is 10 then all the random number will be within 0 to 10.
  • 97. 2.1. ARRAY 233 2Array & Pointer 2.1 Array Arrays in C stores data in a single variable name with an index, also known as a subscript. It is simply a list or ordered grouping for variables of the same type. Arrays often help a programmer in organize collections of data efficiently and intuitively. A character array takes one byte for each character while an integer array takes 4 bytes for one integer. Other datatypes takes appropriate bytes to stores that data type value. A B C D E F ‘0’ myStrA Figure 2.1: Array of first six alphabetic characters stored in memory and pointed by variable ‘myStrA’. 00000001 00000010 myNumA myNumA[0] myNumA[1] Figure 2.2: Array of two integers pointed by variable ‘myNumA’ are stored in memory as shown this figure. Each integer needs four bytes memory space. 2.1.1 Uni-Dimensional Array Arrays are declared by two ways, (i) static and (ii) dynamic. Static arrays are declared using square brackets containing size of array. Dynamic arrays are declared with pointers. In static declaration, compiler creates space required for storing of data at declaration and then returns the address of memory space created. In case of string, one extra space for null terminator is also reserved. In case of dynamic declaration only address of proposed memory space is returned where proposed data may be stored. It does not reserve memory space. To create memory space, function malloc is used. Note that only string arrays have terminating marker (0). Other type of arrays must be controlled by array size. muArrays are declared and initialized like ✞ 1 int numbers [6]; // array declared & space created int point [6]={0 ,0 ,1 ,0 ,0 ,0}; // array declared , space 3 // created and initialized ✌ ✆
  • 98. 234 Array & Pointer Remember that the initialization of static array is take place alongwith its declaration. Otherwise initialization of an array shows compile time error. ✞ 1 char myS []; myS="My String"; /* Illegal initialization .*/ 3 // Actually , above action was copying of data to // array , not initialisation . Copying of data done 5 // by copying character one by one in memory space char myStr []="My String"; /* Legal initialization .*/ ✌ ✆ Initialisation of array with pointer after declaration is compiler dependent. ✞ #include <stdio.h> 2 int main () { 4 char *c = "This "; c = "That "; 6 printf("%s", c); return 0; 8 } ✌ ✆ ✞ That ✌ ✆ The brackets ([ ]) identify ‘numbers’ or ‘points’ and the number enclosed in the brackets indicates the number of elements in the array. An element of the array can be accessed by its index number i.e. subscripts of the array. When square bracket symbol in static array declaration does not contain size of array then it is called dynamic declaration of array. Dynamic array declaration is permitted if it is initialised at the time of declaration. In following example, each element of the array is accessed by its index number. ✞ 1 #include <stdio.h> 3 int main (void ) { int ix; 5 short anArray[ ] = {3, 6, 9, 12, 15}; for (ix = 0; ix < ( sizeof (anArray ) / sizeof ( short)); ++ix) { 7 printf("The array value is %d.n", anArray [ix]); } 9 } ✌ ✆ i0 i1 i2 i3 i4 3 6 9 12 15 anArray Figure 2.3: Head integer value consumes 4 byte memory space. in represents to the index of elements of array ‘days’. Total bytes of memory used to store data is 5 × 4 = 20.
  • 99. 2.1. ARRAY 235 In the above example, the size of the array was not explicitly specified. The compiler knows the size of array from the initialized list. The size of ‘anArray’ is ‘5’ because ‘anArray’ has five elements. Addition of an additional element to the list will increase its size to six. Static declaration of the size of an array, the array list will be overflow. To overcome this problem sizeof expression is used as ✞ 1 size = sizeof(anArray)/ sizeof(short) ✌ ✆ As the sizeof expression in the for loop, the script is automatically adjusted to this change. Designated initializer is allow to pick and choose the initialized elements. If the last element of an array is initialized then in the initialization syntax of traditional C, there is a requirement of initialization of every element preceding to the last one. An array, if initialized, then each element value is index from 0 to n − 1, where n is size of the array. For example, ✞ 1 int count[] = {31, 28, 30, 29, 32, 27}; // array size is 6 ✌ ✆ has six elements. The element value at index 0 is 31, element value at index 1 is 28 and so on. The index of array element may be redefined inside the array as the method given in following syntax ✞ 1 /* int count[] = {[<new index >]=< array element value >};*/ int count[] = {31, [2] = 28, 30, 29, 32, 27}; ✌ ✆ Here, the index of second element is 2, i.e. element shall be stored at third place of memory of integer data type. Elements of an array are overridable, i.e. new element value at index 4 can be override the old value of the element at the index 4 if any other element is assigned the index value 4. ✞ #include <stdio.h> 2 #define MONTHS 12 4 int main (void ) { int days [MONTHS] = {31, 28, [4] = 31, 30, 31, [1] = 29}; 6 int i; for (i = 0; i < MONTHS; i++) 8 printf("%2d %dn", i + 1, days [i]); return 0; 10 } ✌ ✆ In above program example, array ‘days’ has first element (at index position 0) 31, second element (at index position 1) is 28. Next element, 30, of the array ‘days’ is declared for index 4, i.e. for 5th position. Next element is 30 in the array ‘days’. Its position shall be next to the previous element, i.e. after 5th position, therefore this element will be at 6th position or at index position 5. Element for index position 6 is 31. Last element is defined for index position 1. Hence previous element, 28, which was at the index position 1 shall be replaced by value 29. The final arrangement of the array data in the memory shall be as shown in the below figure.
  • 100. 236 Array & Pointer i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 31 29 0 0 31 30 31 0 0 0 0 0 days Figure 2.4: Arrangement of elements of array ‘days’ in memory. Here, each block rep- resents to an integer data byte (i.e. group of four memory bytes). in represents to the index of elements of array ‘days’. ✞ 1 31 2 29 3 0 4 0 5 31 6 30 7 31 8 0 9 0 10 0 11 0 12 0 ✌ ✆ An array initialised with ‘[ ]’ is called expandable array. When an array is declared without its size, compiler first count the array elements and then it grows the array upto a size so that all the elements can stored in the array. ✞ /* Array with growing size . */ 2 int days [ ] = {31, 28, [4] = 31, 30, 31, [1] = 29}; ✌ ✆ ✞ #include <stdio.h> 2 int main (void ) { 4 int days [] = {31, 28, [4] = 31, 30, 31, [1] = 29}; int i; 6 printf("Size of array is %dn", sizeof (days ) / sizeof (int)); /* Here sizeof (days ) / sizeof (int) is not* 8 *grouped as ‘/’ higher precedence to ‘<’ */ for (i = 0; i < sizeof (days ) / sizeof (int); i++) 10 printf("%2d %dn", i , days [i]); return 0; 12 } ✌ ✆ ✞ Size of array is 7 0 31 1 29 2 0 3 0 4 31 5 30
  • 101. 2.1. ARRAY 237 6 31 ✌ ✆ 2.1.2 Multi-Dimensional Array An array declaration in C is given by ✞ int myA[m][n];/*m rows and n cols .*/ ✌ ✆ If the size of integer type array is fixed as shown above, compiler reserves m× n× k bytes memory. Here, k is size of variable data type. For integer it is 4 as integer is 4 bytes long data type. Hence, memory size allocated for integer array of type m × n is 4mn. Assume a 2 × 2 integer array as shown below ✞ 1 int myA [2][2] = { {10, 20}, 3 {15, 2} }; ✌ ✆ The memory allocated for this array is 2 × 2 × 4 = 16 bytes. As column size of this array is 2, hence 8 bytes are taken in a group for two columns, in which each column uses 4 bytes for storing integer data. Remember that, in following figures, each cell represents to one byte. This is why, an integer is represented here as a group of four bytes. It is done, for convenient to calculate the number of bytes required to store an array data. And in computer, the index counting is started from ‘0’ instead of ‘1’. 10 0 0 0 20 0 0 0 15 0 0 0 2 0 0 0 myA c0 c1 r0 r1 In above figure, the byte position of array data is shown into two rows and two column. Practically above data is stored in memory as continuous data bytes. 10 0 0 0 20 0 0 0 15 0 0 0 2 0 0 0 myA 1st row 2nd row 1st col 2nd col 1st col 2nd col From the above arrangement of data, in a multi-dimensional array, number of rows may be constant or variable but number of columns must be constant. The reason is that, elements of an array are arranged one by one sequentially, so if column size is not fixed then pointer-to-array variable will not be able to identify the starting of next row of the array. See the example below:
  • 102. 238 Array & Pointer ✞ #include <stdio.h> 2 int main () { 4 int i; int myA [2][2] = {/* 2X2X4 =16 bytes */ 6 {10, 20}, {15, 2} 8 }; printf("Size of array is %dn", sizeof (myA)); 10 char *p = (char *) &myA; // Cast int into char ptr for (i = 0; i < sizeof (myA); i++) { 12 printf("%d ", p[i]);// print all 16 bytes } 14 return 0; } ✌ ✆ ✞ Size of array is 16 10 0 0 0 20 0 0 0 15 0 0 0 2 0 0 0 ✌ ✆ Now, an array having two columns but dynamic rows is declared and assigned as the syntax is given below: ✞ int myB[ ][2] = { 2 {10, 20}, {15, 2}, 4 {1, 4} }; ✌ ✆ The memory allocated for this array is dynamic. This array has two columns hence memory is allocated in the multiple of 2 × 4 = 8 bytes. If there are two rows then memory allocation will be expanded to 8 × 2 = 16 bytes. Similarly if there are three rows then memory allocation will be expanded to 8 × 3 = 24 bytes and so on, subject to memory sharing is not violated. myA 10 0 0 0 20 0 0 0 15 0 0 0 2 0 0 0 1 0 0 0 4 0 0 0 c0 c1 r0 r1 r2 See the example below: ✞ 1 #include <stdio.h>
  • 103. 2.1. ARRAY 239 3 int main () { int i; 5 /* Array has fixed cols & dynamic rows */ int myB[ ][2] = { 7 {10, 20}, {15, 2}, 9 {1, 4} }; 11 printf("Size of array is %dn", sizeof (myB)); char *p = (char *) &myB; 13 for (i = 0; i < sizeof (myB); i++) { printf("%d ", p[i]); 15 } return 0; 17 } ✌ ✆ ✞ Size of array is 24 10 0 0 0 20 0 0 0 15 0 0 0 2 0 0 0 1 0 0 0 4 0 0 0 ✌ ✆ An array having two rows and three columns is declared and initialized as shown in the syntax given below: ✞ int two_d [2][3] = {{ 5, 2, 1 }, 2 { 6, 7, 8 }}; ✌ ✆ Where [2] represents to the number of rows and [3] represents to the number of columns of the two dimensional array. A three dimensional array is declared as given in the following syntax: ✞ int myA[ ][3][2]; 2 /* | | | * * l r c */ ✌ ✆ This array has two columns (y-axis represented as ‘c’ here), three rows (x-axis represented as ‘r’ here) and variable number of layers (z-axis represented as ‘l’ here). In C programs, which contains three dimensional array, the z-axis (i.e. third dimension) is always outer- most loop. Practically, three dimensional array is layers of two dimensional arrays. As shown in the following figure, a 3 × 2 array is placed in four layers and collectively, they form a 3 × 2 × 4 three dimensional array.
  • 104. 240 Array & Pointer l0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 c0 c1 r0 r1 r2 l1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 c0 c1 r0 r1 r2 l2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 c0 c1 r0 r1 r2 l3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 c0 c1 r0 r1 r2 A three dimensional array is arranged in patterns as shown in below figure. myA l0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 c0 c1 r0 r1 r2 l1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 c0 c1 r0 r1 r2 The memory arrangement of three dimensional array is given in the following figure. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 myA r0 of l0 r1 of l0 c0 of r0 c1 of r0 c0 of r1 c1 of r1 Multi-dimensional array can be used to add, subtract and product (either dot or cross) of two vectors or matrices. Following is an example using an array of 5 × 5 dimension. This example requires 5 × 5 × 4 = 100 bytes. ✞ 1 #include <stdio.h> #define X 5 3 #define Y 5 5 int main (void ) { int ix , iy; 7 short anArray[X][Y]; /* 100 bytes memory requirement .*/ 9 for (ix = 0; ix < X; ++ix) { for (iy = 0; iy < Y; ++iy) {
  • 105. 2.1. ARRAY 241 11 anArray[ix][ iy] = ix * iy; }; 13 } for (ix = 0; ix < X; ++ix) { 15 for (iy = 0; iy < Y; ++iy) { printf("%2dt", anArray[ix][iy]); 17 }; printf("n"); 19 } } ✌ ✆ ✞ 0 0 0 0 0 0 1 2 3 4 0 2 4 6 8 0 3 6 9 12 0 4 8 12 16 ✌ ✆ Multidimentional array can be extended in matrix manipulations, additions, subtractions, multiplications and divisions. In the following example, two matrices are added and subtracted element-wise. The element-wise addition and subtraction is given by Cij = Aij ± Bij ✞ 1 #include <stdio.h> 3 /* Random number generator between 0 to 10.*/ int rand_num (int a, int b) { 5 return ((a * 97 + b*21) & 10); } 7 int main () { 9 int i/* row*/, j/* col*/; 11 int A [3][3]/* First Matrix*/, B [3][3]/* Second Matrix*/, 13 C [3][3]/* Third Matrix*/; printf("First Random Matrix is :n"); 15 /* For each of three rows */ for (i = 0; i < 3; i++) { 17 /* There are three columns.*/ for (j = 0; j < 3; j++) { 19 /* Assign a random matrix elements .*/ A[i][j] = rand_num (i*j, j); 21 printf("%3dt", A[i][j]); } 23 /* Print new line after completion of each row*/ printf("nn"); 25 } printf("nSecond Random Matrix is :n"); 27 /* For each of three rows */
  • 106. 242 Array & Pointer for (i = 0; i < 3; i++) { 29 /* There are three columns.*/ for (j = 0; j < 3; j++) { 31 /* Assign a random matrix elements .*/ B[i][j] = rand_num (i, i*j); 33 printf("%3dt", B[i][j]); } 35 /* Print new line after completion of each row*/ printf("nn"); 37 } printf("nElementwise Addition of Matrix is :n"); 39 /* For each of three rows */ for (i = 0; i < 3; i++) { 41 /* There are three columns.*/ for (j = 0; j < 3; j++) { 43 /* Add matrices elementwise .*/ C[i][j] = A[i][j] + B[i][j]; 45 printf("%3dt", C[i][j]); } 47 /* Print new line after completion of each row*/ printf("nn"); 49 } printf("nElementwise Subtraction of Matrix is :n"); 51 /* For each of three rows */ for (i = 0; i < 3; i++) { 53 /* There are three columns.*/ for (j = 0; j < 3; j++) { 55 /* Subtract matrices elementwise .*/ C[i][j] = A[i][j] - B[i][j]; 57 printf("%3dt", C[i][j]); } 59 /* Print new line after completion of each row*/ printf("nn"); 61 } return 0; 63 } ✌ ✆ ✞ First Random Matrix is : 0 0 10 0 2 8 0 2 10 Second Random Matrix is : 0 0 0 0 2 10 2 8 2 Elementwise Addition of Matrix is : 0 0 10 0 4 18 2 10 12 Elementwise Subtraction of Matrix is : 0 0 10
  • 107. 2.1. ARRAY 243 0 0 -2 -2 -6 8 ✌ ✆ The vector and scalar products between two matrices can also be done. The dot product of two matrices is given by Cij = ~ Aij · ~ Bij In the following example, dot products between to matrices is performed. ✞ #include <stdio.h> 2 /* Random number generator between 0 to 10.*/ 4 int rand_num (int a) { return ((a * 1011457789 + 12345) & 10); 6 } 8 int main () { int i/* row*/, 10 j/* col*/; int A [3][3]/* First Matrix*/, 12 B [3][3]/* Second Matrix*/, C [3][3]/* Dot Matrix */; 14 printf("First Random Matrix is :n"); /* For each of three rows */ 16 for (i = 0; i < 3; i++) { /* There are three columns.*/ 18 for (j = 0; j < 3; j++) { /* Assign a random matrix elements .*/ 20 A[i][j] = rand_num (i + j); printf("%dt", A[i][j]); 22 } /* Print new line after completion of each row*/ 24 printf("nn"); } 26 printf("nSecond Random Matrix is :n"); /* For each of three rows */ 28 for (i = 0; i < 3; i++) { /* There are three columns.*/ 30 for (j = 0; j < 3; j++) { /* Assign a random matrix elements .*/ 32 B[i][j] = rand_num (i * j); printf("%dt", B[i][j]); 34 } /* Print new line after completion of each row*/ 36 printf("nn"); } 38 printf("nDot Product Matrix is :n"); /* For each of three rows */ 40 for (i = 0; i < 3; i++) { /* There are three columns.*/ 42 for (j = 0; j < 3; j++) { /* Elementwise dot product of matrices .*/
  • 108. 244 Array & Pointer 44 C[i][j] = A[i][j] * B[i][j]; printf("%dt", C[i][j]); 46 } /* Print new line after completion of each row*/ 48 printf("nn"); } 50 return 0; } ✌ ✆ ✞ First Random Matrix is : 8 2 2 2 2 0 2 0 8 Second Random Matrix is : 8 8 8 8 2 2 8 2 8 Dot Product Matrix is : 64 16 16 16 4 0 16 0 64 ✌ ✆ The cross product (vector product) of two matrices is given by ~ C = ~ A × ~ B ✞ #include <stdio.h> 2 /* Random number generator between 0 to 10.*/ 4 int newseed =10; int seed (int a){ 6 newseed =newseed+a; return newseed; 8 } int rand_num (int a) { 10 seed (a); return (( newseed * 99991 + 12345) & 10); 12 } 14 int main () { int i/* row*/; 16 int A[3]/* First Vector */, B[3]/* Second Vector */, 18 C[3]/* Dot Vector */; printf("First Random Vector is :n"); 20 /* For each of three rows */ for (i = 0; i < 3; i++) { 22 /* Assign a random vector elements .*/ A[i] = rand_num (i); 24 printf("%dt", A[i]);
  • 109. 2.1. ARRAY 245 } 26 /* Print new line after completion of each row*/ printf("n"); 28 printf("nSecond Random Vector is :n"); 30 /* For each of three rows */ for (i = 0; i < 3; i++) { 32 /* Assign a random vector elements .*/ B[i] = rand_num (i); 34 printf("%dt", B[i]); /* Print new line after completion of each row*/ 36 } printf("n"); 38 printf("nCross Product Vector is :n"); 40 /* For each of three rows */ for (i = 0; i < 3; i++) { 42 /* Elementwise cross product of matrices .*/ C[i] = pow(-1,2* i)* (A[(i+1) %3] * B[(i+2) %3] 44 - B[(i+1) %3] * A[(i+2) %3]) ; printf("%dt", C[i]); 46 } /* Print new line after completion of each row*/ 48 printf("nn"); 50 return 0; } ✌ ✆ ✞ First Random Vector is : 10 2 0 Second Random Vector is : 0 10 8 Cross Product Vector is : 16 -80 100 ✌ ✆ Arrays can be passed to a function as its parameter (argument) as shown in the example given below: ✞ #include <stdio.h> 2 /*+- Array pointer with ** **| expandable size */ 4 void init_array (int a[ ], int count) { int i; 6 for (i = 0; i < count; i++) a[i] = i * 10; 8 for (i = 0; i < count; i++) printf("The a value is %d.n", a[i]); 10 } 12 int main (void ) { int mydata [10];
  • 110. 246 Array & Pointer 14 init_array (mydata , 5); return 0; 16 } ✌ ✆ ✞ The a value is 0. The a value is 10. The a value is 20. The a value is 30. The a value is 40. ✌ ✆ For multidimensional array, there is no limit of dimension in C. Here, a four dimensional matrix is represented by ✞ 1 int myData [2][3][2][4] ✌ ✆ A new dimension in array declaration is always grouped by curly braces. One dimensional array has one curly braces, i.e. one row. In two dimensional array, there are two one dimensional rows both separated by comma (,) operator. These two rows are enclosed by another curly braces. In three dimensional systems of arrays, two 2-dimensional arrays are placed one over another. In the following example, two, three and four dimensional arrays are declared. ✞ 1 #include <stdio.h> 3 int main () { char a[2][2] = { 5 // cols {1, 2}, // row 7 {5, 6} // row }; 9 char b[2][2][2] = { { 11 // cols {1, 2}, // row 13 {5, 6} // row }, 15 {// height {4, 3}, 17 {8, 9} } 19 }; char c[2][2][2][2] = { 21 { { 23 // cols {1, 2}, // row 25 {5, 6} // row }, 27 {// height {1, 2},
  • 111. 2.1. ARRAY 247 29 {5, 6} } 31 }, {// time 33 { {4, 1}, 35 {7, 6} }, 37 { {4, 4}, 39 {9, 1} } 41 } }; 43 int i, j, k, l; printf("Elements of matrix a are n"); 45 for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { 47 printf("Element a[%d][%d] is : %dn", i+1, j+1, a[i][j]); 49 } } 51 printf("Elements of matrix b are n"); for (i = 0; i < 2; i++) { 53 for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { 55 printf("Element b[%d][%d][%d] is : %dn", i+1, j+1, k+1, b[i][j][k]); 57 } } 59 } printf("Elements of matrix c are n"); 61 for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { 63 for (k = 0; k < 2; k++) { for (l = 0; l < 2; l++) { 65 printf("Element c[%d][%d][%d][%d] is : %dn", i+1, j+1, k+1, l+1, c[i][j][k][l]); 67 } } 69 } } 71 return 0; } ✌ ✆ It is an example of the two dimensional matrix in which total and average marks of each student is calculated. ✞ #include <stdio.h> 2 #define STUDENT 3 // number of STUDENTS #define SUBJECT 5 // number of SUBJECT
  • 112. 248 Array & Pointer 4 int main (void ) { 6 // marks of five stus const float marks[STUDENT ][ SUBJECT ] = { 8 // subs -> {9.9, 8.0, 8.3, 4.2, 6.0}, // stu row 10 {9.0, 7.0, 7.3, 2.0, 5.0}, // stu row {9.6, 8.0, 8.8, 2.1, 5.5}, // stu row 12 }; int stu , sub; 14 float subtot , total; printf("Student Marks (Max 50)n"); 16 /* for each stu , sum marks for each sub */ 18 total = 0; for (stu = 0; stu < STUDENT; stu ++) { 20 for (sub = 0, subtot = 0; sub < SUBJECT; sub ++) { subtot += *(*( marks + stu) + sub); 22 } printf("%s %d %20.1fn", "Stu", stu + 1, subtot); 24 total += subtot; /* total for all stus */ } 26 printf("nThe student average is %.1f.nn", total / STUDENT ); 28 printf("Subject Average :n"); 30 printf("Sub_1 Sub_2 Sub_3 Sub_4 Sub_5n"); 32 /* for each sub , sum marks over stus */ for (sub = 0; sub < SUBJECT; sub ++) { 34 subtot = 0; for (stu = 0; stu < STUDENT; stu ++) { 36 subtot += *(*( marks + stu) + sub); } 38 printf("%5.1 f ", subtot / STUDENT ); } 40 printf("n"); return 0; 42 } ✌ ✆ ✞ Student Marks (Max 50) Stu 1 36.4 Stu 2 30.3 Stu 3 34.0 The student average is 33.6. Subject Average : Sub_1 Sub _2 Sub_3 Sub_4 Sub_5 9.5 7.7 8.1 2.8 5.5 ✌ ✆
  • 113. 2.1. ARRAY 249 A multidimensional array may also be returned by a function, if function is used as a pointer. An example for two dimensional array as a returned value of a function is given below: ✞ #include <stdio.h> 2 int (* myF(int arr [3][3] , int n))[3] { 4 int i, j; for (i = 0; i < 3; i++) { 6 for (j = 0; j < 3; j++) { arr[i][j] = i + j; 8 } } 10 return arr; } 12 int main () { 14 int arr [3][3]; int (*q)[3] = myF(arr , 3); 16 int i, j; for (i = 0; i < 3; i++) { 18 for (j = 0; j < 3; j++) { printf(" %d", q[i][j]); 20 } printf("n"); 22 } } ✌ ✆ ✞ 0 1 2 1 2 3 2 3 4 ✌ ✆ 2.1.3 Array of Strings It is very simple to declara an array for integers, float, characters datatypes as they has fixed size. But, in case of string, declaration of array is complex as size of string, being stored in array like matrix form, is variable. For example, at a particular cell, we can store string “me” or string “our”. Here, both words have different size. So, declaration of an array for string needs special caution and care. Here, we shall discuss about the storing of string data in an array, starting from one dimensional array to multi-dimensional array. Suppose we have to store string “This”. We declare array like ✞ 1 char myArr []; ✌ ✆ Here, ‘[]’ controls the size of declared variable ‘myArr’ as dynamic and memory is allocated and reallocated by compiler at run time according to the size of input string being stored. Now, we store string “This” in this array, and appended by null terminator. The memory data shall be looked like-
  • 114. 250 Array & Pointer 0×0012 0×0013 0×0014 0×0015 0×0016 0×0017 0×0018 0×0019 myArr T h i s 0 Figure 2.5: But what happens if we declare an fixed size one dimensional array as shown below: ✞ 1 char myArr [10]; ✌ ✆ It means, above array may store only 10 characters including null terminator. ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 char myArr[]="This "; printf("String is ’%s ’n",myArr); 7 return 0; } ✌ ✆ ✞ String is ’This ’ ✌ ✆ If we try to store string of size more than 10 characters, data shall be overflow. From figure 2.5, it is seen that each character of string ‘This’ is column of one row vector. Therefore, when we declare a two dimensional array, one new parameter is required for rows of the array alongwith other size of string parameter. ✞ 1 char myArr[<rows >][< string size in each row >] ✌ ✆ For example, an array ✞ 1 char myArr [3][5] ✌ ✆ tells us that, there are three rows and each row may store strings of five characters including null terminator. Note that, the declaration parameter ‘[<string size in each row >]’ is required only at the time of array declaration. When storing and retrieving of strings, we just ignore it or just replace it by ‘[0]’ only.
  • 115. 2.1. ARRAY 251 0×0012 0×0013 0×0014 0×0015 0×0016 T h i s 0 i s 0 m y 0 0×0312 0×0313 0×0314 0×0315 0×0316 p e t 0 myArr[0] myArr[1] myArr[3] Figure 2.6: ✞ 1 #include <stdio.h> #include <string.h> 3 int main () { 5 char myArr [4][5]={ "This ","is","my","pet"}; printf("String is ’%s ’n",myArr[0]) ; 7 printf("String is ’%s ’n",myArr[1]) ; printf("String is ’%s ’n",myArr[2]) ; 9 printf("String is ’%s ’n",myArr[3]) ; return 0; 11 } ✌ ✆ ✞ String is ’This ’ String is ’is ’ String is ’my ’ String is ’pet ’ ✌ ✆ Note that, a string variable is pointer of itself and points to address where data is stored. So, use of ‘&’ symbol is optional. It also points to the address of first character of string, so use of ‘[0]’ is also optional. So that, ‘myArr’ and ‘myArr[0]’ both return the string ‘This’. ✞ #include <stdio.h> 2 #include <string.h> 4 int main () { char myArr [4][5]={ "This ","is","my","pet"}; 6 printf("String is ’%s ’n",myArr); printf("String is ’%s ’n",myArr[1]) ; 8 printf("String is ’%s ’n",myArr[2]) ; printf("String is ’%s ’n",myArr[3]) ; 10 return 0; } ✌ ✆ ✞ String is ’This ’
  • 116. 252 Array & Pointer String is ’is ’ String is ’my ’ String is ’pet ’ ✌ ✆ We can also declare an array that is arranged in rows and columns and each column is of fixed size for storing of strings. ✞ char myArr[<rows >][< cols >][< string size >] ✌ ✆ 0×0012 0×0013 0×0014 0×0015 0×0016 T h i s 0 0×0017 0×0018 0×0019 0×0020 0×0021 T h a t 0 i s 0 w a s 0 m y 0 m y 0 0×0312 0×0313 0×0314 0×0315 0×0316 p e t 0 0×0317 0×0318 0×0319 0×0320 0×0321 p e n 0 myArr[0][0] myArr[1][0] myArr[3][0] myArr[0][1] Figure 2.7: See the example below: ✞ 1 #include <stdio.h> #include <string.h> 3 #define ROWS 4 5 #define COLS 2 #define STRING_SIZE 5 7 int main () { 9 char myArr[ROWS ][ COLS ][ STRING_SIZE ] = { {"This ", "That "}, 11 {"is", "was"}, {"my", "my"}, 13 {"pet", "pen"} }; 15 int i; printf("Data matrix is : n"); 17 for (i = 0; i < ROWS ; i++) { printf("%5s t %5sn", myArr[i][0], myArr[i][1]); 19 } return 0; 21 } ✌ ✆ ✞ Data matrix is : This That is was
  • 117. 2.1. ARRAY 253 my my pet pen ✌ ✆ We can add new strings in this array by using strcpy function by indicating the address of matrix cell. ✞ 1 /*At fifth row , first column */ strcpy(arr [4][0] , "Hi"); 3 /*At fifth row , second column*/ strcpy(arr [4][1] , "His"); ✌ ✆ While we use scanf function to add user’s input from input stream, we should exactly known to the address of memory byte where data is to be stored. ✞ #include <stdio.h> 2 #include <string.h> 4 #define ROWS 5 #define COLS 2 6 #define STRING_SIZE 5 8 int main () { char myArr[ROWS ][ COLS ][ STRING_SIZE ] = { 10 {"This ", "That "}, {"is", "was"}, 12 {"my", "my"}, {"pet", "pen"} 14 }; int i; 16 printf("Enter data for 5th row 1st column :"); scanf("%s", myArr [4][0]) ; 18 printf("Enter data for 5th row 2nd column :"); scanf("%s", &myArr [4][1][0]) ;/* last [0] is optional */ 20 printf("Data matrix is : n"); for (i = 0; i < ROWS ; i++) { 22 printf("%5s t %5sn", myArr[i][0], myArr[i][1]); } 24 return 0; } ✌ ✆ ✞ Enter data for 5th row 1st column :hi Enter data for 5th row 2nd column :his Data matrix is : This That is was my my pet pen hi his ✌ ✆ We can also declare a static multidimensional array by using pointers. It is declared as
  • 118. 254 Array & Pointer ✞ char * myArr[<rows >] ✌ ✆ Data should be assigned at the time of declaration. Pointer character ‘*’ is responsible for dynamic allocation of memory of suitable size so that assigned data is stored in the array. See the example below: ✞ 1 #include <stdio.h> 3 int main () { /* Static array declaration */ 5 char * myArr[2] = {"This ", "is"}; printf("First row string is : %sn", myArr[0]) ; 7 printf("Second row string is : %s", myArr[1]) ; return 0; 9 } ✌ ✆ ✞ First row string is : This Second row string is : is ✌ ✆ 0×0012 0×0013 0×0014 0×0015 0×0016 T h i s 0 0×0112 0×0113 0×0114 0×0115 0×0116 i s 0 myArr[0] myArr[1] Here, two strings have static storage prior to the program startup. In the initializer, the arrays are converted to pointers to char and the words array is initialized with the pointer values. It can not be modified during the program run. It has its own advantages as we can access to character of string by using pointers. ✞ #include <stdio.h> 2 int main () { 4 char * myArr[3] = {"This ", "is"}; printf("First row string is : %sn", myArr[0]) ; 6 printf("Same from index 1 is : %s n", (myArr [0]+1)); return 0; 8 } ✌ ✆ ✞ First row string is : This First row string from index 1 is : his ✌ ✆ Here, ‘myArr[0]+1’ means pointer points to the first row string at index ‘0’ and pointer position is changed by one character position rather than next row.
  • 119. 2.1. ARRAY 255 0×0012 0×0013 0×0014 0×0015 0×0016 T h i s 0 0×0112 0×0113 0×0114 0×0115 0×0116 i s 0 myArr[0]+1 myArr[1] Using pointer, we can access whole string or its part of string. For example, ‘*myArry’ is the same as myArry[0]. ‘(*myArry)[0]’ is the same as **myArry, which is the first character of the string and not the address of the string. ✞ #include <stdio.h> 2 int main () { 4 char * myArr[2] = {"This ", "Home "}; printf("For ’This ’ : %sn", myArr [0]) ; 6 printf("For ’Home ’ : %sn", myArr [1]) ; /* Address of ’This ’ pointed by * myArr and* 8 *it points to address of character ’T’ */ printf("For ’This ’ : %sn", *myArr); 10 /* Dereference to pointer that is pointing * *to address where string ’This ’ is stored. * 12 *Pointer points to location of character ’T ’.*/ printf("For ’T’ : %c n", ** myArr); 14 /* same as above*/ printf("For ’T’ : %c n", (* myArr)[0]) ; 16 /* Dereference to pointer that is pointing * *to address where string ’This ’ is stored.* 18 *Pointer in incremented by one , and now , * *it points to location of character ’h ’. */ 20 printf("For ’h’ : %c n", (* myArr)[1]) ; /* same as above*/ 22 printf("For ’h’ : %c n", *(* myArr +1)); return 0; 24 } ✌ ✆ ✞ For ’This ’ : This For ’Home ’ : Home For ’This ’ : This For ’T’ : T For ’T’ : T For ’h’ : h For ’h’ : h ✌ ✆ 2.1.4 Array in Function In functions arguments are passed to it as value unless the function needs alter the argument. If function needs update the argument, argument should be passed to function as its argument. Arrays can also passed to functions as pointers. If an array is passed to
  • 120. 256 Array & Pointer the function, function would have to allocate enough space to hold a copy of the original array and then copy all the data from the original array to the new array. It is much quicker to pass the address of the array rather than array itself and have the function work with the original data. Prototype for the passing of an array to the function is ✞ 1 int sum(int arr[ ]) /*Or*/ 3 int sum(int *arr) ✌ ✆ sum() i0 i1 i2 i3 i4 3 6 9 12 15 anArray S Figure 2.8: Passing of address of array to sum() function. Array is pointed by the pointer/variable ‘anArray’. In C, array parameters are always treated as pointers. C compilers do not check the size of the array passed to the function hence for good programming, the function should know the limits of actions on the array. This is why a new parameter of array size as ‘n’ is passed to the function as ✞ 1 int sum(int arr[ ], int n) ✌ ✆ sum() for(i=0; i<n; i++){ S += anArray[i]; } i0 i1 i2 i3 i4 3 6 9 12 15 anArray n S Figure 2.9: Passing of address of array as well as element size of the array to sum() function. Array is pointed by the pointer/variable ‘anArray’. Because the name of an array is the address of the first element, an actual argument of an array name requires that the matching formal argument be a pointer. In this context int arr[ ] to mean the same as the int * arr. First bracket in the multidimensional array may be empty or not but other brackets should contains the valid integers for the size of the array dimension. For example
  • 121. 2.1. ARRAY 257 ✞ 1 int sum(int arr[ ][ ], int rows ); // faulty declaration ✌ ✆ is a faulty declaration. Recall that the compiler converts array notation to pointer no- tation. It means, that arr[1] will become arr+1. For the compiler to evaluate this, it needs to know the size of object to which ‘arr’ points. The declaration ✞ 1 int sum2 (int arr[ ][4], int rows ); // valid declaration ✌ ✆ says that ‘arr’ points to an array of four integers, so ‘arr+1’ means “add 16 bytes to the address”. If first bracket contains a number then it will be ignored. ✞ 1 int sum2 (int ar [3][4] , int rows ); // valid declaration , 3 ignored ✌ ✆ ✞ 1 #include <stdio.h> #define ROWS 3 3 #define COLS 4 int sum(int rows , int cols , int ar[rows ][ cols ]); 5 int main (void ) { 7 int i,j; int varr [ROWS ][ COLS ]; 9 for (i = 0; i < ROWS ; i++) for (j = 0; j < COLS ; j++) 11 varr [i][j] = i * j + j; printf("3x4 Array n"); 13 printf("Sum of all elements = %dn", sum(ROWS , COLS , varr )); 15 return 0; } 17 int sum(int rows , int cols , int ar[rows ][ cols ]) { int r; 19 int c; int tot = 0; 21 for (r = 0; r < rows ; r++) for (c = 0; c < cols ; c++) 23 tot += ar[r][c]; return tot; 25 } ✌ ✆ ✞ 3x4 Array Sum of all elements = 36 ✌ ✆ An array can passed to a function by using function prototype as shown in syntax given below: ✞ #include <stdio.h> 2 void PrintIt (char Str[ ]) { 4 printf("%sn", Str);
  • 122. 258 Array & Pointer } 6 int main () { 8 char label[ ] = "Allora Caves."; PrintIt (label); 10 return 0; } ✌ ✆ The output is ✞ Allora Caves. ✌ ✆ Function PrintIt() expects a character array. When an array is declared as the parameter to a function, it really gets a pointer. Arrays are always automatically passed by reference. Similarly a pointer can also pass to a function as an array or as a pointer. ✞ 1 #include <stdio.h> 3 void PrintIt (char Str[ ]) { printf("%sn", Str); 5 } 7 int main () { char * label = "Allora Caves."; 9 PrintIt (label); return 0; 11 } ✌ ✆ The output is ✞ Allora Caves. ✌ ✆ ✞ 1 #include <stdio.h> 3 void PrintIt (char *Str) { printf("%sn", Str); 5 } 7 int main () { char * label = "Allora Caves."; 9 PrintIt (label); return 0; 11 } ✌ ✆ The output is ✞ Allora Caves. ✌ ✆ Unfortunately, (in C and C++) the length of the array cannot be obtained from an array passed to a function at run time, because the size of an array is not stored anywhere. The compiler always replaces sizeof () with a constant. See the following example
  • 123. 2.1. ARRAY 259 ✞ 1 #include <stdio.h> #include <string.h> 3 #define NUM_ELEM (x) (sizeof (x) / sizeof (*(x))) 5 int sum(int input_array [ ]) { 7 int sum_so_far = 0; int i; 9 /* Would NOT Work ; input_array was* *not defined in this function . */ 11 for (i = 0; i < NUM_ELEM (input_array ); i++){ sum_so_far += input_array [i]; 13 }; return ( sum_so_far ); 15 } 17 int main (int argc , char *argv [ ]) { int left_array [ ] = {1, 2, 3}; 19 int right_array [ ] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; int the_sum = sum(left_array ); 21 printf("the sum of left_array is: %d n", the_sum ); the_sum = sum(right_array ); 23 printf("the sum of right_array is: %d n", the_sum ); 25 return 0; } ✌ ✆ When this example is run, it gives output as shown below ✞ the sum of left _array is 1 the sum of right_array is 10 ✌ ✆ whatever the values are passed as argument in the sum function. This ‘sum()’ routine needs to handle more than just one constant length of an array. There are some common ways to work around this fact: 1. Write the function as required, for each array parameter and parameter “length” which has type “size t”. We can use sizeof () at the point where this function is called. 2. Use of a null-terminated string to mark the end of the array if array is string. Arrays representing to numbers does not need the null-terminating string to mark of the end of array. Instead it, number arrays are passed to the function along with its element size. 3. Pass the arrays as well as array length parameter to the function. We can pass the pointer-to-array if required. Evaluate the data as per rules set by function statements or expressions. Using these facts, above example is now modified as given below.
  • 124. 260 Array & Pointer ✞ #include <stdio.h> 2 #define NUM_ELEM (x) (sizeof (x) / sizeof (*(x))) 4 int mySum(int array[ ], size_t length) { 6 int sum = 0; int i; 8 for (i = 0; i < length; i++) { sum += array[i]; 10 }; return ( sum); 12 } 14 int main (int argc , char *argv [ ]) { int sum; 16 int i_array [ ] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; /* Works here , because the size of right_array * 18 *is passed to the sum function as argument */ sum = mySum(i_array , NUM_ELEM (i_array )); 20 printf("The sum is : %d.n", sum); 22 return 0; } ✌ ✆ Output of above example is ✞ the sum is : 55 ✌ ✆ The same method of passing an array to a function and getting sum of all array element is also possible with other number datatypes. Above example is suitable modified for array contains floating type numbers. ✞ 1 #include <stdio.h> 3 #define NUM_ELEM (x) (sizeof (x) / sizeof (*(x))) 5 /* Function returns floating data . So mySum()* *should be declared as floating data type . */ 7 float mySum(float in_array [ ], size_t length) { float sum = 0; 9 int i; for (i = 0; i < length; i++) { 11 sum += in_array [i]; }; 13 return ( sum); } 15 int main (int argc , char *argv [ ]) { 17 float sum; float array[ ] = {10.10 , 50.50 , 4.57, 1.21}; 19 sum = mySum(array , NUM_ELEM (array));
  • 125. 2.1. ARRAY 261 printf("The sum is : %fn", sum); 21 return 0; } ✌ ✆ ✞ The sum is : 66.379997 ✌ ✆ It’s worth mentioning that sizeof () operator has two variations: sizeof (type) and sizeof (<expression>). An example using sizeof () function to a pointer is shown below. ✞ 1 #include <stdio.h> #include <string.h> 3 int main (int argc , char *argv [ ]) { 5 char buffer [10]; if (argc < 2) { 7 fprintf (stderr , "USAGE: %s stringn", argv [0]) ; return 1; 9 } strncpy (buffer , argv [1], sizeof ( buffer)); 11 buffer[sizeof (buffer) - 1] = ’0 ’; return 0; 13 } ✌ ✆ Output of the script is ✞ USAGE: executable .exe string ✌ ✆ 2.1.5 String As Array C has no built in string handling facilities. Consequently, string is defined as array of characters. C allows a character array to be represented by a character string rather than a list of characters, with the null terminating character, automatically added to the end. Example of string array is shown below. ✞ 1 char s[ ] = {’A’, ’p’, ’p’, ’l’, ’e’, ’s’, ’0’}; ✌ ✆ A p p l e s 0 s Figure 2.10: Array of characters constructing word ‘Apples’ is stored in memory and pointed by variable ‘s’. Normally size of string array is controlled at initialisation. An string array can store only the number of characters upto its length. Rest of the characters are ignored. In following example only ten characters will be stored in the string array ‘mystr’.
  • 126. 262 Array & Pointer ✞ 1 char mystr [10] = "Apple is red."; ✌ ✆ It is convenient to let the compiler determine the array size. If one omits the size in an initializing declaration, the compiler determines the size for supplied string. In following example, compiler set the string length of thirteen characters. ✞ 1 char mystr[ ] = "Apple is red."; ✌ ✆ A pointer notation may aslo be set up to represent a string. In pointer notation, above example will be look like ✞ 1 const char *ptrstr = "Delhi"; ✌ ✆ D e l h i 0 ptrstr Figure 2.11: Character array ‘Delhi’ stored in memory. ‘ptrstr’ points to the character array ‘Delhi’. Both declarations amount to saying that ‘ptrstr’ is a pointer to the indicated string. Strings as array or pointer, are same but only the pointer version can use the increment operator while array version does not support increment operator. To create an extra long string, string is splitted into multiple sections, by closing the first section with a quote, and recommencing the string on the next line (also starting and ending in a quote): ✞ 1 char string[ ] = "This is a very , very long " "string that requires two lines."; ✌ ✆ See the example below ✞ #include <stdio.h> 2 int main () { 4 char ch; char string[ ] = "Two lines " 6 "string."; int i = 0; 8 while (string[i] != ’0’) { ch = string[i]; 10 printf("%c.", ch); i++; 12 } return (0); 14 } ✌ ✆
  • 127. 2.1. ARRAY 263 ✞ T.w.o. .l.i.n.e.s. .s.t.r.i.n.g... ✌ ✆ When an array is assigned the characters to get the string, there must be a terminating null character. Otherwise there shall be garbage output. For example following syntax has no terminating null character. It is not in standard format. ✞ 1 char a[10]; a[0]= ’a’; 3 a[1]= ’r’; a[2]= ’u’; ✌ ✆ This format should be like ✞ char a[10]; 2 a[0]= ’a’; a[1]= ’r’; 4 a[2]= ’u’; a[3]= ’0’; ✌ ✆ See following two examples, in which string is terminating without and with null character. First example gives garbage output (see below). ✞ 1 #include <stdio.h> 3 int main () { char a[10]; 5 a[0]= ’a’; a[1]= ’r’; 7 a[2]= ’u’; printf("%s",a); 9 return 0; } ✌ ✆ ✞ <garbage output > ✌ ✆ In this second example, string is terminated with null character. This example gives output what we required. ✞ 1 #include <stdio.h> 3 int main () { char a[10]; 5 a[0]= ’a’; a[1]= ’r’; 7 a[2]= ’u’; a[3]= ’0’; 9 printf("%s",a); return 0; 11 } ✌ ✆
  • 128. 264 Array & Pointer ✞ aru ✌ ✆ Size of static array should be larger by one to the original data size being stored in the array. This extra byte is for NULL terminator, i.e. 0. To store one byte data, array size should be larger than one. For storing n byte data, array size should be > n. Here two examples are given. In first example, array size is equal to the data size and in second example, array size is larger than data size by one. This extra one byte is used to store null terminating character. ✞ 1 #include <stdio.h> #include <stdlib.h> 3 int main (void ) { 5 /* Deficient static array * * size declared as char c.*/ 7 char c[1]; printf("Enter char ’e’ : "); 9 gets (c); if (( strcmp(c, "e") == 0)) 11 printf("%sn", c); return 0; 13 } ✌ ✆ On compilation, it gives error while following example gives desired output. ✞ 1 #include <stdio.h> #include <stdlib.h> 3 int main (void ) { 5 /* Suficient static array * * size declared as char c.*/ 7 char c[2]; printf("Enter char ’e’ : "); 9 gets (c); if (( strcmp(c, "e") == 0)) 11 printf("%sn", c); return 0; 13 } ✌ ✆ ✞ e ✌ ✆ In first example, array ‘c’ can store only character ‘c’. There is no extra space to store null terminating character. It makes that array ‘c’ does not hold string in proper format. In second example, array ‘c’ can store one character as well as null terminating character. By this way it holds string in proper format. 2.1.6 Size of Array C features two kinds of arrays: static (compile-time, fixed size) and dynamic (allocated at run-time). The length of a dynamic array cannot be acquired from the array itself -
  • 129. 2.1. ARRAY 265 its length must be stored elsewhere. The size of static array is computed as ✞ 1 int length = sizeof(<array name >) / sizeof(<array element >); ✌ ✆ Preprocessor ways for array length is defined as ✞ 1 #define ARRAY_LENGTH (A) (sizeof(A) / sizeof(A[0]) ) ✌ ✆ i0 i1 i2 i3 i4 3 6 9 12 15 anArray n Figure 2.12: Size of ‘anArray’ is the number of elements pointed by ‘anArray’. Here remember that array is of integer type, hence each element shown in this figure needed 4 bytes long memory space. There are 5 elements in this array, so size of ‘anArray’ is 5 (n = 5) and these elements needed 5 × 4 = 20 bytes long memory space. Array becomes pointer when it is passed as a parameter to a function. Thus, the length of an array parameter may not require directly but a dedicated length parameter is required and should be passed to the function. See the following example is given string array ‘fruit’ is declared with static size of 2 elements in each row while each row is pointed by ‘fruit’ pointer itself. Hence the element size is fixed so, there is no need to calculate the length size of array. But in this example, length is computed by using above syntax. ✞ 1 #include <stdio.h> 3 int main (){ const char *fruit[2] = { "apples", "oranges" }; 5 /* Length of the array by dividing * 7 *the size of all elements by the* *size of the first element. */ 9 int length = sizeof(fruit) / sizeof(fruit[0]) ; 11 printf("%dn", length); 13 return 0; 15 } ✌ ✆ ✞ 2 ✌ ✆ In above example, length of the array is obtained by dividing the size of all elements (found with sizeof (fruit)) by the size of the first element. Note that since the array elements are pointers to null-terminated character arrays, the size of the first element is actually the size of the pointer type - not the length of the string. This size, regardless of the type being pointed to, is 8 bytes, 4 bytes, or 2 bytes on 64-bit, 32-bit, or 16-bit
  • 130. 266 Array & Pointer platforms respectively. Pointer can be used for variable size array as shown in example below. ✞ 1 #include <stdio.h> /* Variable size array.*/ 3 char *name ; int main () { 5 name ="My School!!"; int i=0; 7 while(name [i] !=’0 ’){ printf("%cn",name [i]); 9 i++; } 11 return 0; } ✌ ✆ ✞ M y S c h o o l ! ! ✌ ✆ 2.1.7 Vector & Matrix Vector is a one dimensional array or a matrix having one rows and multiple columns. A vector is represented by A = [1, 2, 3, 5]. A matrix is vertical arrangement of vectors. Vec- tors are one dimensional arrangement of coefficients of variables of an algebraic equation. Let an algebraicequation ax + by = k, that is written as ax + by − k = 0 Now, vector u for this algebraic equation is given by u = [a, b, −k] If there is a set of two algebraic equations, ax + by − k = 0 cx + dy − l = 0 Then two vectors of these two algebraic equations are u and v respectively as u = [a, b, −k]; v = [c, d, −l]
  • 131. 2.1. ARRAY 267 The matrix arrangement like AX = B is a b −k c d −l   x y 1   = 0 0 Here, matrix A is row arrangement of two vectors u and v. Similarly, for example, vectors A = [1, 2, 3, 5] and B = [5, 4, 3, 2] form a matrix when these vectors are arranged vertically. C =
  • 135. 1 2 3 5 5 4 3 2
  • 139. Here, C is a 2 × 4 matrix. A one dimensional vector is defined in C like ✞ #include stdio.h 2 int main (void ) { 4 int A[5]; int i; 6 for (i = 1; i 5; i++) { A[i] = i; 8 } for (i = 1; i 5; i++) { 10 printf(%dt, A[i]); } 12 return 0; } ✌ ✆ ✞ 1 2 3 4 ✌ ✆ A matrix is defined in C like ✞ 1 #include stdio.h 3 int main (void ) { int A [2][5]; 5 int i, j; for (i = 0; i 2; i++) { 7 for (j = 0; j 4; j++) { A[i][j] = i + j; 9 } } 11 for (i = 0; i 2; i++) { for (j = 0; j 4; j++) { 13 printf(%dt, A[i][j]); } 15 printf(nn, A[i][j]); } 17 return 0; } ✌ ✆
  • 140. 268 Array Pointer ✞ 0 1 2 3 1 2 3 4 ✌ ✆ In C, arrays, vectors and matrices are defined in same ways. 2.1.8 Sparse Matrix A sparse matrix is one which have majority number of zeros along rows and columns. For example a sparce matrix is S =       0 0 0 0 0 0 1 2 0 1 0 2 1 0 2 0 0 0 0 0 0 1 2 0 1       C program for sparse matrix is given below: ✞ 1 #include stdio.h #include time .h 3 int main () { 5 time_t t1 , t2; t1 = time (NULL ); 7 static int array [10][10]; int i, j, m = 5, n = 5; 9 int counter = 0; for (i = 0; i m; ++i) { 11 for (j = n; j 0; --j) { t2 = time (NULL ); 13 array[i][j] = (i * j + t2) % (t1 % 5 + 1); if (array[i][j] == 0) { 15 ++ counter ; } 17 } } 19 printf(Matrix is : n); for (i = 0; i m; ++i) { 21 for (j = 0; j n; ++j) { printf(%dt, array[i][j]); 23 } printf(n); 25 } if (counter ((m * n) / 2)) { 27 printf(Matrix is sparse matrix n); } else { 29 printf(Matrix is not a sparse matrix n); } 31 printf(There are %d number of zeros.n, counter );
  • 141. 2.2. POINTER 269 return 0; 33 } ✌ ✆ Above proram uses the current CPU time so each time when program is run, a different matrix is generated. The matrix generated may be a sparse matrix or not. The one run state matrix generated by above program is given below, which is not a sparse matrix. ✞ Matrix is : 0 4 4 4 4 0 0 1 2 3 0 1 3 0 2 0 2 0 3 1 0 3 2 1 0 Matrix is not a sparse matrix There are 4 number of zeros. ✌ ✆ 2.2 Pointer A pointer is a simple variable that stores the address (the location in memory) of a value in memory rather than storing data itself. A variable is said to be declared as a pointer if it prefixed with an asterisk symbol. A variable name with prefixed ampersand () defines the address of itself. A pointer with prefixed asterisk, except declaration, refers to the value of the variable whose address is pointed-by the pointer. The address to which pointer points is called pointee address. 0×50 0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59 0×0504 int *i; pointer address pointee address There are two valid pointer operations, (i) comparison of two pointers and (ii) addi- tion or subtraction. Address of memory cell and value stored at that memory cell both constitute different meanings. Memory is array of many bits which is capable of storing values either binary 1 or binary 0. This size of memory has no meaning as it can not store large numeric value, so multiple bits are grouped to form bytes (one byte has 8 bits). Too store an integer, 4 bytes (32 bits) are grouped together. See the following constitution of memory cells. 0×1001 0×1005 0×1009 0×1013 Value at memory cell Address of memory cell 00000000 00000000 00000011 11101001
  • 142. 270 Array Pointer In which, each memory cell or memory location is identified by its address and it contains a value. See an example given below. Read program line-by-line alongwith comments carefully. ✞ #include stdio.h 2 int main (){ /*i points to memory location where 10 is stored. */ 4 int i=10; 6 /* Pointer j points to a random address */ int *j; 8 /* Now j points to same address as i is pointing . */ 10 j=i; // i and j points to same address. 12 /*j stored value at its address.*/ *j=20; 14 /*As i and j points to same memory location * 16 *( addresses ) therefore , values of i and j * *are equal. So , i = 20. */ 18 printf(%d,i); //i has same value as j; return 0; 20 } ✌ ✆ ✞ 20 ✌ ✆ An array name is also the address of the first element of the array. That is, if ‘arr’ is an array, then ✞ 1 arr == arr [0]; // name of array is the // address of the first element ✌ ✆ Both ‘arr’ and ‘arr[0]’ represent the memory address of first element of the array. It is also called the reference of the array ‘arr’. A pointer can points to any element of the array, if the pointer is assigned address of that element. In the following example, pointer ‘x’ points to the address of first element of the array ‘i’. ✞ #include stdio.h 2 int main () { 4 int i[5] = {10, 20, 30, 40, 50}; int *x = i[0]; /* Points to first element.*/ 6 printf(%d, *x); return 0; 8 } ✌ ✆
  • 143. 2.2. POINTER 271 0×10 10 0×11 20 0×12 30 0×13 40 0×14 50 i[ ] x The output of above program shall be ✞ 10 ✌ ✆ If above example is modified as given below, then the pointer ‘x’ points to the 3rd element of the array ‘i’. ✞ 1 #include stdio.h 3 int main () { int i[5] = {10, 20, 30, 40, 50}; 5 int *x = i[2]; /* Points to third element.*/ printf(%d, *x); 7 return 0; } ✌ ✆ 0×0 10 0×1 20 0×2 30 0×3 40 0×4 50 i[ ] x The output of above program shall be ✞ 30 ✌ ✆ If an integer is pointed by a pointer-to-char variable, then this variable can points to the address of each byte of the integer variable (integer variable is 4 bytes long). ✞ 1 #include stdio.h 3 int main () { /* 1000 D = 1111101001 B*/ 5 int i = 1001; /* Pointer casting from integer to character .*/ 7 char *x = (char *) i; /* Little endian is x[0]=11101001 B* 9 *Big endian is x[1]=00000011 B* *Big endian x[2]= x[3]=00000000 B*/ 11 /* Print little endian x[0]*/ printf(%d, (int) x[0]) ; 13 return 0; } ✌ ✆
  • 144. 272 Array Pointer x[3] x[2] x[1] x[0] i: x 00000000 00000000 00000011 11101001 Output of above program is ✞ -23 ✌ ✆ ✞ 1 #include stdio.h 3 int main () { /* 1000 D = 1111101001 B*/ 5 int i = 1001; /* Pointer casting from integer to character .*/ 7 char *x = (char *) i; /* Little endian is x[0]=11101001 B* 9 *Big endian is x[1]=00000011 B* *Big endian x[2]= x[3]=00000000 B*/ 11 /* Print big endian x[1]*/ printf(%d, (int) x[1]) ; 13 return 0; } ✌ ✆ x[3] x[2] x[1] x[0] i: x 00000000 00000000 00000011 11101001 Output of above program is ✞ 3 ✌ ✆ Though, the pointers allow increment and decrement operations but they are not preferred over indexed arrays when there is requirement of random access. In indexed arrays, fifth element can be accessed by myArr[4]. But in pointer array, we have to first reach at the address of fifth element by using pointer increments or decrements operations and then dereference the pointer. So, pointer requires extra coding to reach at desire destination. Identification of Pointer Type We know that, in C, a variable is declared as ✞ 1 datatype var name ; ✌ ✆ There are three main form of variable object declarations. (i) normal variables, (ii) arrays and (iii) functions. Their prototypes are respectively
  • 145. 2.2. POINTER 273 ✞ 1 int i; // normal variable int k[10]; // array variable 3 int f(); // function variable ✌ ✆ In above three declarations, priority is observed to identify the type of variable. In first case, variable ‘i’ is normal integer type variable which stores integer values. It means where ever it stores a value, it will be an integer. Priority of variable literal is lower than square brackets or parentheses. A variable is followed by square brackets, then it is treated as an array. Similarly, if a variable is followed by parentheses, then it is treated as function. Now, the question is, how we identify the nature of variable when asterisk is prefixed to variable literals to make it pointer variable as shown below: ✞ 1 int *i; int *k[10]; 3 int *f(); ✌ ✆ Its answer is again priority listing. The priority of pointer symbol (asterisk) is less than array symbol or parentheses. Hence first declaration is pointer to integer. In second declaration, priority of variable ‘k’ goes with array symbol and asterisk makes it pointers. Hence, it will be pronounce as “array k of pointers-to-integers”. Note that, datatype only told about the type of data pointed by the pointers, not about the type of pointer itself. Similarly, third declaration is “function which returns a pointer pointing-to-an-integer value”. Remember, array always stores values and function always returns a value. Now, parentheses are used to change the priority of asterisk like ✞ 1 int *i; int (*k)[10]; 3 int (*f)(); ✌ ✆ The first declaration has no change. It is pointer to an integer. In second declaration, priority of asterisk goes with ‘k’. Hence it is pronounce as “pointer ‘k’ to an array (due to presence of square bracket) of integers (array stores integer type values)”. Similarly third declaration is pronounced as “pointer ‘f’ points to a function (due to presence of parentheses) which returns an integer value”. So, be careful while using pointers with specific priorities. There is not change in the priority if data type is changed. For example, only stored value at pointee address is changed to real (double data type) from integer if above declaration is modified as ✞ 1 double *i; double (*k)[10]; 3 double (*f)(); ✌ ✆ 2.2.1 Declaring pointers When a variable name is preceded by asterisk symbol during its declaration, it is called pointer variable. In the following variable declarations:
  • 146. 274 Array Pointer ✞ 1 long *var1 , var2 ; // Declaration of pointer int **p3; // Declaration of pointer to a pointer ✌ ✆ In line 1, ‘var1’ is declared as a pointer variable to a long data type, i.e. data stored at the pointed-to address will be long data type. And ‘var2’ is declared as a long data type variable and it is not a pointer to a long data type as it is not preceded by asterisk symbol. In line 2, ‘p3’ is declared as a pointer to a pointer to an int data type. Data types which precedes to a pointer variable during pointer declaration specify about the data read or write at the address pointed-to by the pointer variable. If data type is char type, then will be read at the address location in group of one byte. If data type is int type, then data will be read at the address location in group of four bytes and so on. Remember that uninitialized pointers results in dangling or wild pointers, therefore each pointer declared must be initialized as NULL pointer. ✞ int *p = NULL ; // Declaration initialization of pointer ✌ ✆ It is also safe to initialized a pointer to NULL when its allocated memory is freed by using free() function. ✞ 1 int *p = NULL ; // Declaration initialization of pointer p=malloc (10) ; // Allocate memory space 3 free (p); // Free memory space allocated to pointer p=NULL ; // Initialize NULL to pointers ✌ ✆ Pointer types are often used as parameters to function calls. ✞ int MyFunction ( struct MyStruct *pStruct ); ✌ ✆ In the above syntax, it is explained that how to declare a function which uses a pointer as an argument. Since C passes function arguments by value, in order to allow a function to modify a value from the calling routine, a pointer to the value must be passed. Pointer- to-Structure is also used as function arguments even when nothing in the struct will be modified in the function. This is done to avoid copying the complete contents of the structure onto the stack. A simple example is ✞ 1 #include stdio.h #include time .h 3 void getSeconds (unsigned long *par); 5 int main () { unsigned long sec; 7 getSeconds ( sec); printf(No. of seconds since 01 Jan 1970: %ldn, sec); 9 return 0; } 11 void getSeconds (unsigned long *par) { 13 *par = time (NULL ); return; 15 } ✌ ✆
  • 147. 2.2. POINTER 275 ✞ No. of seconds since 01 Jan 1970: 1420616845 ✌ ✆ Solved Problem 2.1 See the following memory arrangement. A pointer variable is declared and assigned address as given in below code lines. What will be the print output? Solution The memory arrangement is : 0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59 00000000 00000000 10010101 10110101 10110101 11111111 10011101 10101101 10010001 ✞ 1 char *ptr =0 x53; printf(%d, *ptr); ✌ ✆ Here, pointer is declared as char type, hence it shall read data stored at address 0×53 in a group of one byte (byte group size is equal to the size of char data type). 0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59 00000000 00000000 10010101 10110101 10110101 11111111 10011101 10101101 10010001 So, the printf function will give output in decimal form which is equal to the value stored at the address of 0×53. From the memory arrangement, value is 100101012, that is decimal equivalent to 14910. Solved Problem 2.2 See the following memory arrangement. A pointer variable is declared and assigned address as given in below code lines. What will be the print output? Solution The memory arrangement is : 0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59 00000000 00000000 10010101 10110101 10110101 11111111 10011101 10101101 10010001 ✞ short *ptr =0 x53; 2 printf(%d, *ptr); ✌ ✆ Here, pointer is declared as short type, hence it shall read data stored at address 0×53 in a group of two bytes (bytes group size is equal to the size of short data type). 0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59 00000000 00000000 10010101 10110101 10110101 11111111 10011101 10101101 10010001 So, the printf function will give output in decimal form which is equal to the value stored in two consecutive bytes whose first byte is at the address of 0×53. From the memory arrangement, value is 10010101101101012, that is decimal equivalent to 3832510.
  • 148. 276 Array Pointer Solved Problem 2.3 See the following memory arrangement. A pointer variable is declared and assigned address as given in below code lines. What will be the print output? Solution The memory arrangement is : 0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59 00000000 00000000 10010101 10110101 10110101 11111111 10011101 10101101 10010001 ✞ short *ptr =0 x53; 2 printf(%d, *( ptr ++)); ✌ ✆ Here, pointer is declared as short type, hence it will point to address of data stored from address 0×53 onward in a group of two bytes (bytes group size is equal to the size of short data type). The increment of pointer ‘ptr++’ will increase the address pointed by the pointer variable ‘ptr’ by two bytes (equal to the size of declaration data type, here it is short). 0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59 00000000 00000000 10010101 10110101 10110101 11111111 10011101 10101101 10010001 Thus the address pointed by the pointer variable ‘ptr’ is 0×55. So, the printf function will give output in decimal form which is equal to the value stored in two consecutive bytes whose first byte is at the address of 0×55. From the memory arrangement, value is 10110101111111112, that is decimal equivalent to 4659110. Assigning values to pointers A pointer variable points to an address. So, its value is always an address of other variable. The address of a variable is accessed by using ‘address of’ operator, represented by symobl ‘’. The standard procedure of assigning value to a pointer variable is shown in the following code snippets. ✞ /*An interger variable that have * 2 *null value stored in memory. */ int myInt; 4 /* Pointer that addresses to a integer value.*/ int *ptr; 6 /* Address to the pointer where * *myInt value is stores in memory.*/ 8 ptr = myInt; ✌ ✆ Here, ‘ptr’ will now reference to ‘myInt’. Pointers can also be assigned to dynamically allocated memory. See the following example. ✞ #include stdio.h 2 int j, k; int *ptr; 4
  • 149. 2.2. POINTER 277 int main (void ) { 6 j = 1; k = 2; 8 ptr = k; printf(j has value %d and stored at %pn, j, (void *) j); 10 printf(k has value %d and stored at %pn, k, (void *) k); printf(‘ptr’ = %p and stored at %pn, ptr , (void *) ptr); 12 printf(Value of the integer pointed -by ‘ptr’ is %dn, *ptr); return 0; 14 } ✌ ✆ ✞ j has value 1 and stored at 0x403100 k has value 2 and stored at 0x403120 ‘ptr ’ has value 0x403120 and stored at 0x403110 Value of the integer pointed -by ‘ptr ’ is 2 ✌ ✆ 2 0×50 3 0×51 4 0×52 5 0×53 6 0×54 7 0×55 8 0×56 int *ptr = k k k A pointer is created by using asterisk (*) as shown in the first line of the below code. Method of value assignment to the variable is shown in second line of the following code. ✞ int *j; 2 j = 5;/* Valid good practice .*/ ✌ ✆ This type of assignment updated value stored at the address of pointer variable itself. In above type of pointer assignment, pointer now points to the memory whose address is 0×05. See the example ✞ #include stdio.h 2 int main () { 4 int *j; j = 5; /* Valid good practice .* 6 *It accepts address. */ printf(j is : %dn, j);// prints address pointed 8 //by the pointer variable return 0; 10 } ✌ ✆ ✞ j is : 5 ✌ ✆ As pointers holds the address of other variables or objects, hence what ever value is assigned to pointers is treated as memory address. Note that, addresses are represented
  • 150. 278 Array Pointer in hexa-decimal form, hence all other values are converted into equivalent hexadecimal values. Method of assigning a value to a pointer as shown below is invalid. This is due to assigning value to an uninitialised pointer. An uninitialized pointer points to null memory address. So, when we tries to update the value at the memory address that is pointed by the pointer, it shows errors. ✞ 1 int *j;// No address with pointer to point. *j = 5;/* Invalid as it tries to alter value * 3 * stored at address pointed by j. * *It is very bad practice . */ ✌ ✆ A pointer points to the memory location (address) where value is stored. Pointer does not store value itself. So, pointer does not know where value is stored. If we try to do so, the program either may crash or it damaged to the system. A best practice of assigning a pointer is explained in the following example. ✞ #include stdio.h 2 int main () { 4 int i = 0; int *j; 6 j = malloc (2 * sizeof (int)); j = 5; /* valid good practice to assign address */ 8 printf(j is : %dn, j);// prints address j = 6; /* valid good practice to assign address */ 10 printf(j is : %dn, j);// prints address return 0; 12 } ✌ ✆ ✞ j is : 5 j is : 6 ✌ ✆ Another example ✞ #include stdio.h 2 int main (void ) { 4 int i; int *p; 6 p = i; /* valid for best practice */ i = 10; /*i is now 10 */ 8 *p = 20; /* valid*/ /* prints 20*/ 10 printf(i is %dn, i); /* Prints value stored at address pointed by the pointer.*/ 12 printf(i is %dn, *p); return 0; 14 } ✌ ✆
  • 151. 2.2. POINTER 279 ✞ i is 20 i is 20 ✌ ✆ Pointer Dereferencing (Value Finding) Pointer dereferencing or value finding or indirection is a method to extract the value stored at given memory address. To access a value to which a pointer points, the ‘*’ operator is used. Another operator, the ‘–’ operator is used in conjunction with pointers to structures. To understand dereferencing, take a memory arrangement as shown below: A 0×11 B 0×12 C 0×13 D 0×14 E 0×15 F 0×16 G 0×17 H 0×18 I 0×19 Now, we declare a pointer and assign an address as ✞ char *x = 22; 2 printf(%c, *x); ✌ ✆ 0×2A 00010110 ∗x It does not gives character whose character code is equal to 22 but it gives the character that is stored at address of 0×16 (decimal 22 and binary 00010110). And from the above memory arrangement, it is character F. There can use ‘’ and ‘*’ alternatively. Here operator ‘*’ is used for dereferencing and the operator ‘’ is used to get the address. When they are used in group, they cancel the effect of each other. See the example below: ✞ #include stdio.h 2 int main () { 4 char *p = Lucknow is capital city of UP.; /* See the sequence of and *. */ 6 printf(%sn, ** p); char *q = Delhi is capital city of India.; 8 /* Sequence of and * is changes */ printf(%sn, ** q); 10 return 0; } ✌ ✆ ✞ Lucknow is capital city of UP. Delhi is capital city of India. ✌ ✆ Again see the modified form of above example.
  • 152. 280 Array Pointer ✞ #include stdio.h 2 int main () { 4 char *p = Lucknow is capital city of UP.; printf(%cn, ***p); 6 return 0; } ✌ ✆ ✞ L ✌ ✆ Here, ‘p’ is a pointer to first character of string, which is L. *p gives us L, *p gives address of L, **p again L, **p address of L, and finally ***p gives ‘L’. In case of integer type variables, variables points to the address where integer value is stored. When integer type variables are passed to function as its parameter, then we can either pass the value of the integer type variable or address of the variable. Address of integer type variable is fetched by using ‘’ symbol while the value at the address is catch by using ‘*’ symbol. ✞ 1 #include stdio.h 3 /* Catch value of i as j. Catch the* *value of from address of i as k.*/ 5 void catchI(int j, int *k) { /* The value of parameter k is not * 7 * assigned to any integer variable ,* * hence when we want to print it , * 9 * it must be dereferece first as k * * is still pointing to address of i*/ 11 printf(%d %dn, j, *k); } 13 int main () { 15 int i = 3; catchI(i, i); 17 return 0; } ✌ ✆ ✞ 3 3 ✌ ✆ Now, a question rises that do we can access the value stored at memory by referencing to its address? For example, consider memory arrangement as shown below: 0×1001 0×1005 0×1009 0×1013 Value at memory cell Address of memory cell (i) 00000000 00000000 00000011 11101001
  • 153. 2.2. POINTER 281 A variable (i) points to the address of 0×1013 where data 11101001 is stored in binary format. When we reference to variable (i), we get the value 233 in decimal. Do we can find the value by dereferencing ∗0×1013? The answer is NO, because, 0×1013 is pure integer and dereferencing can only performed on expression of type pointer. So, to get the value from the address 0×1013 we should type cast it like ✞ 1 *( int *) 0 x1013 ✌ ✆ Note that, while we access memory address directly, the System OS may prevent to do so due to memory sharing violation or access violation. See the example below, in which printf tries to print the value stored at address 102010 which is primarily reserved for the application of OS. ✞ 1 #include stdio.h 3 int main (int argc , char ** argv ) { printf(%d.n ,*(int *) 1020); 5 } ✌ ✆ Addition of pointers Following is an example in which addition of a pointer and an integer is explained. ✞ 1 #include stdio.h /* Note that it accepts a pointer to an int */ 3 void increment (int *p){ *p = *p + 1; /* dereference p and add 1 */ 5 } 7 int main (void ) { int i = 20; 9 /* i value is 20 */ printf(i is %dn, i); 11 /* Pass integer to increment function as pointer */ increment (i); 13 /* Prints the value 21*/ printf(i is %dn, i); 15 return 0; } ✌ ✆ ✞ i is 20 i is 21 ✌ ✆ The value of a pointer is the address of the object to which it points. The address of a large object, such as type double variable, typically is the address of the first byte of the object. Applying the * operator to a pointer yields the value stored in the pointed-to object. Adding 1 to the pointer increases its value by the size, in bytes, of the pointed-to type. In following prototypes
  • 154. 282 Array Pointer ✞ arr + 2 == arr [2] /* Same address */ 2 *( arr + 2) == arr [2] /* Same value */ ✌ ✆ Again *(arr+2) with *arr+2 are different to each other. The indirection operator (*) binds more tightly (that is, has higher precedence) than +. ✞ *( arr + 2) /* Value of the 3rd element of dates */ 2 *arr + 2 /* 2 added to the value of the 1st element */ ✌ ✆ Pointer address can be changed by using pointer increments. If ‘a’ is a pointer address then ‘a++’ shall be next pointer address. The increments or decrements is equal to the size of data type of pointer. For example, if pointer addresses to a character data type, then its jump is multiple of four bytes. If pointer addresses to an integer data type, then its jump is multiple of one byte. In the following example, the pointer address of pointer ‘name’ is increased by one byte and the value at that pointer location is retrieved and printed in console output. ✞ #include stdio.h 2 /* Pointer array.*/ char *name ; 4 int main () { name =My School!!; 6 /* While pointer value is not null .*/ while(* name !=’0’){ 8 /* Print the pointer value.*/ printf(%cn ,*name ); 10 /* Increase the pointer location .*/ name ++; 12 } return 0; 14 } ✌ ✆ ✞ M y S c h o o l ! ! ✌ ✆ Now a question rises, what happen if a pointer reaches beyond the string length. Answer is, that it starts pointing to the any string supplied as stdin by program itself or by user. Escape characters if present are skipped. See the example below: ✞ 1 #include stdio.h
  • 155. 2.2. POINTER 283 /* Pointer array.*/ 3 char *name ; 5 int main () { name = My School; /* string length is 11*/ 7 int i = 0; /* Points to 20 characters started * 9 *from 0 location of name pointer .*/ while (i 20) { 11 /* *name first puts the value of* *string while i =11. When the * 13 *supplied string is ended , it * *starts pointing to the stdin * 15 *string Value at pointer ..... */ printf(Value is : %cn, *name ); 17 /* Increase the pointer location .*/ name ++; 19 i++; } 21 return 0; } ✌ ✆ ✞ Value is : M Value is : y Value is : Value is : S Value is : c Value is : h Value is : o Value is : o Value is : l Value is : Value is : V Value is : a Value is : l Value is : u Value is : e Value is : Value is : i Value is : s Value is : Value is : : ✌ ✆ See another example given below. ✞ #include stdio.h 2 /* Pointer array.*/ char *name ; 4 int main () { 6 name = My School!!;
  • 156. 284 Array Pointer int i = 0; 8 /* While pointer value is not null .*/ while (* name != ’0 ’) { 10 /* If i is larger than 5.*/ if (i 5) { 12 /* Decrease the pointer location by 5.*/ name = name - 5; 14 /* Reset i.*/ i = 0; 16 /* Print new line .*/ printf(n); 18 } /* Print the pointer values.*/ 20 printf(%c, *name ); /* Increase the pointer location .*/ 22 name ++; /* Increase i by one.*/ 24 i++; } 26 return 0; } ✌ ✆ ✞ My Sch y Scho Schoo School chool! hool !! ✌ ✆ Passing of Pointers Value assigned to one pointer can be passed to other pointer. Actually, values of both pointers are not copied mutually but pointers are set to point the value of other pointer. See the example given below: ✞ #include stdio.h 2 #include stdlib.h 4 int main () { /* Pointer array.*/ 6 int *x,*y, *z,i=0; x = malloc(sizeof(int)*100); 8 y = malloc(sizeof(int)*100); while(i10) { 10 x[i] = i; y[i] = 3*i; 12 i++; } 14 i=0; printf(Original data is : nx t yn);
  • 157. 2.2. POINTER 285 16 while(i 5){ printf(%d t, x[i]); 18 printf(%d t, y[i]); printf(n); 20 i++; } 22 /* Mutually transfer the pointers .*/ z=x[0]; 24 x=y[0]; y=z[0]; 26 i=0; printf(nPassing the Pointer , data is : nx t yn); 28 while(i 5){ printf(%d t, *x); 30 printf(%d t, *y); printf(n); 32 x++; y++; 34 i++; } 36 return 0; } ✌ ✆ ✞ Original data is : x y 0 0 1 3 2 6 3 9 4 12 Passing the Pointer , data is : x y 0 0 3 1 6 2 9 3 12 4 ✌ ✆ 2.2.2 Pointers and Arrays String is an array of characters. In other words, an array contains arranged characters one after another. For example ✞ 1 char label[ ] = Single;/* implicitly representation */ ✌ ✆ arranges characters in memory as
  • 158. 286 Array Pointer S i n g l e 0 Memory location of the array may be anywhere. The location of array is known as address of the string. Here ‘0’ is null character represents to the end of string. The available spaces (size) of a character array may be larger than the number of characters of abstract string to be held in it. See the example given below. ✞ 1 char label [10] = Single;/* explicitly representation */ ✌ ✆ Characters are arranged in memory like S i n g l e 0 0 0 0 In above type of representation of array is called static representation, because size of allocated memory or size of array is determined at the time of program compilation. When size of array is specified, the number of elements is at least one more than the length of string. Any unused elements are automatically initialized to null character ‘0’. Pointer can hold only an address and they cannot hold all the characters of the character array. It means, special symbol ‘*’ (asterisk) is used to keep track of a string rather than string itself. ✞ 1 char name [ ] = Arun ; char status [10] = Married ; 3 char *Ptr; Ptr = name ; ✌ ✆ The first memory byte of the above variables, i.e. ‘name’, ‘status’ and ‘Ptr’ assumed to be at the location 0×40, 0×50 and 0×60 respectively. The memory arrangement for the ‘name’ variable will be as 0×40 0×41 0×42 0×43 0×44 A r u n 0 The memory arrangement of the variable ‘status’ will be as 0×50 0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59 M a r r i e d 0 0 0 and memory arrangement of the pointer variable ‘Ptr’ with holding the address of the variable ‘name’ will be looked like: 0×60 0×61 0×62 0×40
  • 159. 2.2. POINTER 287 During the assignment of a pointer to the address of a string array, the pointer must be a character pointer (type of data it points at the address it stored). To assign the address of an array to a pointer, address-of () operator is not used since the name of an array behaves like an address of that array in this context (array name, either string or integer, acts as address itself). A pointer is a non constant pointer1 that points to a non constant string2 where as arrays is a constant pointer3 which points to a non constant string4 . The interaction of pointers and arrays have two fundamental statements about them. 1. A variable declared as an array of some type acts as a pointer to that type. When used by itself, it points to the first element of the array. 2. A pointer can be indexed like an array name. Often, the first case is seen when an array is passed to a function as an argument. The function declares the parameter as a pointer, but the actual argument may be the name of an array. The second case occurs when dynamically allocated memory is accessed. Pointer reference example is given below. ✞ #include stdio.h 2 int main (){ int a[10], *iptr ; 4 iptr = a; *iptr = 5;// update the value of a[0] 6 printf(The first element is %d,iptr [0]) ; return 0; 8 } ✌ ✆ ✞ The first element is 5 ✌ ✆ A function which can accept a pointer, can also accept an array. Pointers also follow the rules of array and array increment processing. ✞ 1 #include stdio.h int my_array [ ] = {1,23,17,4,-5,100}; 3 int *ptr; int main (void ){ 5 int i; /* Point our pointer to the * 7 *first element of the array*/ ptr = my_array [0]; 9 for (i = 0; i 6; i++){ 11 printf(my_array [%d] = %d , i, my_array [i]); printf(ptr + %d = %dn, i, *( ptr + i)); 1 The address it holds can be updated/changed. 2 String size is dynamic as pointer points to the address of first character of string. 3 Array name always points to that address at which its data is stored. This address can not be changed as if it is changed, array name starts pointing to something else. 4 String size is dynamic as pointer points to the address of first character of string.
  • 160. 288 Array Pointer 13 } return 0; 15 } ✌ ✆ ✞ my_array[0] = 1 ptr + 0 = 1 my_array[1] = 23 ptr + 1 = 23 my_array[2] = 17 ptr + 2 = 17 my_array[3] = 4 ptr + 3 = 4 my_array[4] = -5 ptr + 4 = -5 my_array[5] = 100 ptr + 5 = 100 ✌ ✆ The average example is given below. ✞ #include stdio.h 2 double getAverage (int *arr , int size ); int main () { 4 int balance [5] = {200, 20, 30, 40, 50}; double avg; 6 avg = getAverage ( balance , 5 ) ; printf(Average value is: %fn, avg ); 8 return 0; } 10 double getAverage (int *arr , int size ){ 12 int i, sum = 0; double avg; 14 for (i = 0; i size ; ++i){ sum += arr[i]; 16 } avg = (double)sum / size ; 18 return avg; } ✌ ✆ ✞ Average value is: 68.000000 ✌ ✆ A function should never return a pointer to a local variable, even when the compiler not complains. When declaring an array as variable of the function without size, it is equivalent to declared pointer. Often this is done to emphasize the fact that the pointer will be used in a manner equivalent to an array. In the following example ✞ 1 #include stdio.h 3 void main (void ) { char str_arr[ ] = This is string array.; 5 char *str = This is string pointer .; int i = 0; 7 while (i 10) { printf(%stt%sn, str_arr ++, str ++); 9 i++; }
  • 161. 2.2. POINTER 289 11 return 0; } ✌ ✆ Increment and decrement operation is not allowed in arrays while pointers accepts incre- ment or decrement operations. It is because ‘str arr’ is a fixed address variable. A pointer can points to the address of specific index element. It can be done like ✞ char s[ ]={ ’a’, ’b’, ’c’, ’d’}; 2 /* char a is at index 0. * *char b is at index 1. * 4 *char c is at index 2. * *char d is at index 3. */ 6 p = s[3]; /* Pointer grabs the address of* *3rd index element of array s*/ ✌ ✆ Note that pointers assigns address among them. For example, if ‘p’ and ‘q’ are pointer variables, and ‘q’ points to the memory address 0×04, then ‘p=q’, pointer ‘p’ shall points to the same address, i.e. to memory address 0×04. See the complete example, that is given below: ✞ 1 #include stdio.h 3 int main (void ) { char s[ ] = {’a’, ’b’, ’c’, ’d’, ’e’, ’n’, ’c’, ’0’}; 5 char *p, *q, *r; p = s[3]; /* Pointer grabs the address of* 7 *3rd index element of array s*/ q = p; /* address assignment from p to q*/ 9 r = s; /* address assignment from s to r*/ printf(Pointer p points to %cn, *p); 11 printf(Pointer q points to %cn, *q); printf(Pointer r points to %cn, *r); 13 return 0; } ✌ ✆ ✞ Pointer p points to d Pointer q points to d Pointer r points to a ✌ ✆ Pointers to Multidimensional Arrays A two dimensional array may be declared be normal array method or by pointer method. A two dimensional array by pointer method is declared as shown in the following syntax. ✞ 1 int (* mArr )[2]; ✌ ✆ Here, ‘mArr’ is a pointer-to-array of two columns. Parentheses are used to make prece- dence of pointer symbol (*) higher than the square bracket operator ([ ]). Square bracket operator ([ ]) has a higher precedence than dereferencing operator (*). Therefore, a declaration such as
  • 162. 290 Array Pointer ✞ 1 int *mArr [2]; ✌ ✆ is invalid. An example, in which two dimensional array by pointer method is initialized and its elements are printed in output console. ✞ 1 #include stdio.h 3 int main (void ) { int *mPtr [ ][3] = { 5 {-1, 2, 3}, {4, -3, 5}, 7 {5, 6, -5} }; 9 // int *mPtr [3] = {1, 2, 3}; int i, j; 11 for (i = 0; i 3; i++) { for (j = 0; j 3; j++) { 13 printf(%2dt, *(* mPtr + (3 * i) + j)); } 15 printf(n); } 17 return 0; } ✌ ✆ ✞ -1 2 3 4 -3 5 5 6 -5 ✌ ✆ Pointers as Function Argument Sometime it may be an requirement to invoke a function with an argument that is itself a pointer. A function with a pointer is assigned as ✞ 1 int sum(int * arr); // Valid prototype int sum(int *); // Valid prototype ✌ ✆ sum() gets the address of the first element of the array, and it learns that it will find an integer at that location. This prototype function does not tell the size of array. The more flexible approach of the function is ✞ int sum(int * arr , int n); ✌ ✆ Here ‘arr’ is a pointer to the first element of array and ‘n’ is size of the array. In many instances, the variable is itself a parameter for the current function and may be a pointer to some type of structure. The ampersand character () is not needed in this circumstance to obtain a pointer value, as the variable is itself a pointer. ✞ 1 #include stdio.h
  • 163. 2.2. POINTER 291 double getAverage (int *arr , int size ); 3 int main () { int balance [5] = {200, 20, 30, 40, 50}; 5 double avg; avg = getAverage (balance , 5); 7 printf(Average value is: %fn, avg); /* Size of the balance in bytes.*/ 9 printf(The size of balance is %zd bytes.n, sizeof balance ); return 0; 11 } 13 double getAverage (int *arr , int size ) { int i, sum = 0; 15 double avg; for (i = 0; i size ; ++i) { 17 sum += arr[i]; } 19 avg = (double) sum / size ; /* array ’arr’ is not as long as balance , because * 21 * it is not array itself. It represents to the * * position of first bytes of the array ‘balance ’.*/ 23 printf(The size of arr is %zd bytes.n, sizeof arr); return avg; 25 } ✌ ✆ ✞ The size of arr is 4 bytes. Average value is: 68.000000 The size of balance is 20 bytes. ✌ ✆ Consider another piece of code as given below. In this example, enum data type is used to define index position of rainbow colors by color name. For example, ‘red’ is at index position ‘0’, ‘orange’ for index ‘1’ and so on. These index values of rainbow colors are accessed by ‘colour’ variable in for() loop as well as these index values are used to get the color name from ‘rainbow’ array. ✞ 1 #include stdio.h 3 enum spectrum { red , orange , yellow , green , blue , indigo , violet 5 } colour; 7 char *rainbow [ ] = {red, orange, yellow, green, blue , indigo, violet}; 9 int main () { 11 for ( colour = red; colour = violet; colour ++) { printf(%s , rainbow [colour ]); 13 } printf(n); 15 return 0;
  • 164. 292 Array Pointer } ✌ ✆ ✞ red orange yellow green blue indigo violet ✌ ✆ In following example pointers are used simply for swapping of two integers of variables from each other. Integer type variables are pointers by default. Hence, to pass the values, assigned to integer type variable, to a function, ‘’ symbol is prefixed to the variables to pass the address of the variable value stored in the memory. ✞ 1 #include stdio.h void swap (int *x, int *y); 3 int main () { 5 int a = 2, b = 3; printf(Swapping of values of a and b.n); 7 printf(Value of a is %d and value of b is %d.n, a, b); swap (a, b); 9 printf(Value of a is %d and value of b is %d.n, a, b); return 0; 11 } 13 void swap (int *x, int *y) { int t = *x; 15 *x = *y; *y = t; 17 return; } ✌ ✆ ✞ Swapping of values of a and b. Value of a is 2 and value of b is 3. Value of a is 3 and value of b is 2. ✌ ✆ In the definition of swap() function inside the main function, variables ‘a’ and ‘b’ are used as addresses. In prototype they are declared as pointers. Because ‘a’ and ‘b’ are integers so, ‘x’ and ‘y’ are pointers to integers. Hence the prototype function is declare as ✞ 1 void swap (int *x, int *y) ✌ ✆ Above example is rewritten as shown below. This modified example does not swap the values of integer variables ‘a’ and ‘b’. On passing of values ‘a’ and ‘b’ to swap() function, local variable ‘a’ becomes 2 and ‘x’ becomes 3. Again ‘y’ becomes 2. In this swapping, there is no change in the value of ‘b’. This is why, there is no swapping of values between variables ‘a’ and ‘b’. ✞ 1 #include stdio.h 3 void swap (int x, int y); int main () { 5 int a = 2, b = 3;
  • 165. 2.2. POINTER 293 printf(Swapping of values of a and bn); 7 printf(Value of a is %d and value of is %d.n, a, b); swap (a, b); 9 printf(Value of a is %d and value of is %d.n, a, b); return 0; 11 } 13 void swap (int x, int y) { int a = x; 15 x = y; y = a; 17 return; } ✌ ✆ ✞ Swapping of values of a and b Value of a is 2 and value of is 3. Value of a is 2 and value of is 3. ✌ ✆ In function call by passing the address of a variable is also possible. The function accepts a pointer and modified the value at the address of this pointer. Local variable is passed as address to the function, the value of local variable is modified accordingly. ✞ 1 #include stdio.h 3 void myFunc(int *p) { /* Parameter as pointer to integer */ *p = 30; /* Modify the value at the address of pointer */ 5 } 7 int main () { int i = 20; /* Local variable with value 20*/ 9 myFunc (i); /* Address of local var passed to function */ printf(%d, i); /* Print modified value here . It is 30 now*/ 11 return 0; } ✌ ✆ ✞ 30 ✌ ✆ A function may also be declared as pointer and it returns the address of pointer variable being returned by retunrn keyword within its code body. See the following example: ✞ 1 #include stdio.h 3 /* Function shall return address* *of data it has manipulated . * 5 *Catch the address of myStr * *where it is stored in memory.*/ 7 char *myF(char *ch) { /* return the address that was* 9 *caught by function through * *its arguments char *ch */
  • 166. 294 Array Pointer 11 return ch; } 13 /* Function shall return address of that * 15 *data , which it has manipulated . Catch* *address of myStr , stored in memory. */ 17 char *myF2 (char *ch) { /* Get string through the address * 19 *caught through argument and * *manipulate string in memory. */ 21 ch [5]= ’X’;/* change alphabet F-X* *using index method. */ 23 ch ++; /* Increase address by one* 25 *Now , it points to ‘B’ */ 27 /* return the address that was* *catched by function through* 29 *its arguments char *ch */ return ch; 31 } 33 int main () { /* Declare a pointer and assign string to it.* 35 *Memory allocated internally as declaration * *and initialization takes simultaneously . * 37 *In case of later assignment , first create * *memory using malloc () then copy string. */ 39 char * myStr = ABCDEFGHIJKLMNOPQRSTUVWXYZ; //OR 41 // char myStr[27] = ABCDEFGHIJKLMNOPQRSTUVWXYZ; 43 /* string variables or string pointers * *acts as their addresses . This is why* 45 * *myStr shows error as we are trying* *to convert address (numeric value) * 47 *into pointers . */ printf(%26sn, myF(myStr)); 49 printf(%26sn, myF2 (myStr)); return 0; 51 } ✌ ✆ ✞ ABCDEFGHIJKLMNOPQRSTUVWXYZ BCDEXGHIJKLMNOPQRSTUVWXYZ ✌ ✆ Address as Function Argument We can pass an address to a function as its argument. The value of the variable at its address is extracted in the function. This value is used in the expressions or the
  • 167. 2.2. POINTER 295 statements in function body. In example given below, integer variable ‘i’ is scanned as integer and stored in the memory address. Address of this variable is passed to function ‘ZeroCumSum’. In the function, value of the address is extracted by dereference and used in the cumulative sum expressions. ✞ #include stdio.h 2 /* Catch address through function argument .*/ int ZeroCumSum (int *i) { 4 int sum =0; /*Do what algorithm said .*/ 6 while (*i 0) { sum += *i; 8 (*i) --; } 10 /* Return result.*/ return sum; 12 } 14 int main () { /* Initialize the variables .*/ 16 int i, csum ; /* Enter a number.*/ 18 printf(Enter a number: ); scanf(%d, i); 20 /* Get cumulative sum. Here , * *i is passed to function as* 22 *as an address argument . */ csum = ZeroCumSum (i); 24 /* Print output.*/ printf(Cumsum is %dn, csum ); 26 return 0; } ✌ ✆ ✞ Enter a number: 10 Cumsum is 55 ✌ ✆ The parameter data type of argument in a function must be same as the data type whose addresses is being passed to the function. ✞ #include stdio.h 2 #include string.h 4 /* Parameter is flaot type , same as * *datatype whose address is passed.*/ 6 void outv (float *f) { printf(%fn, *f); 8 return; } 10 int main () { 12 /* Float data type variable */
  • 168. 296 Array Pointer float f=12.5; 14 /* Address of float type variable */ outv (f); 16 return 0; } ✌ ✆ ✞ 12.5 ✌ ✆ Another example with double data type variable. ✞ 1 #include stdio.h #include string.h 3 /* Parameter is flaot type , same as * 5 *datatype whose address is passed.*/ void outv (double *f) { 7 printf(%lfn, *f); return; 9 } 11 int main () { /* Float data type variable */ 13 double f=12.5; /* Address of double type variable */ 15 outv (f); return 0; 17 } ✌ ✆ ✞ 12.5 ✌ ✆ Passing of address of the structures as function parameter is explained in the following example. ✞ 1 #include stdio.h #include string.h 3 struct s { 5 double d; }; 7 /* Parameter is struct type , same as * 9 *datatype whose address is passed. */ void outv (struct s *f) { 11 printf(%lfn, f-d); return; 13 } 15 int main () { /* Structure variable */ 17 struct s myS;
  • 169. 2.2. POINTER 297 myS.d = 11.5;// Assignment 19 /* Pass address of structure */ outv ( myS); 21 return 0; } ✌ ✆ ✞ 11.500000 ✌ ✆ Pointer Equivalent to Array A pointer type **p is also represents to an array type arr[ ][ ]. Here [ ][ ] represents to dynamic size of array in two dimensions. Here first asterisk in **p represents to number of the rows while second asterisk represents to dynamic size of each row. It should be remember that, the dynamic length should that dimension which is used to store new data. For example, in two dimensional matrix, column length is fixed and row length is dynamic. So, ✞ 1 /* Fixed col (k) length and variable row length*/ int myA[ ][k]; ✌ ✆ represents to a two dimensional matrix with fixed length of columns and variable length of rows. Arrays declared with variable size returns compile time error if they are not initialized. ✞ #include stdio.h 2 int main () { 4 int mat [][3];/* variable row declaration .*/ return 0; 6 } ✌ ✆ Above example shall return compile time error as the array is not fixed or initialized. Now above code is modified as shown in the following example. ✞ #include stdio.h 2 int main () { 4 /* Array with variable rows declared initialized .*/ int mat[ ][3]={}; 6 int myA [2][3]; /* fixed size declaration .*/ return 0; 8 } ✌ ✆ Now, above example will compile without showing any error. Again, in three dimensional array, rows and columns are fixed in length while layer length (z-axis) is dynamic. So, a three dimensional array is represented as ✞ /* Fixed row (x) col (y) and variable layers*/ 2 int myA[ ][x][y]; ✌ ✆
  • 170. 298 Array Pointer A two dimensional array having ‘m’ rows and ‘n’ columns is equivalent to pointer as shown in the syntax given below: ✞ arr[m][n] = *(*( p + m) + n) ✌ ✆ Two dimensional array can be pointed by a pointer variable. Value at the address pointing to an element of the array can be obtain by de-reference. The two dimensional reference is done as shown in the table below. Pointer Equals Array *(*(p + 0) + 0) *(*(p)) p[0][0] *(*(p + 0) + 1) *(*(p) + 1) p[0][1] *(*(p + 1) + 0) *(*(p + 1)) p[1][0] *(*(p + 1) + 1) *(*(p + 1) + 1) p[1][1] *(*(*(p + 0) + 0) + 2) *( **p + 2 ) p[0][0][2] *(*(*(p + 0) + 1) + 0) **(*p + 1 ) p[0][1][0] *(*(*(p + 0) + 0) + 0) ***p p[0][0][0] Table 2.1: Pointer and its equivalent to array. The pointer of a multi-dimensional matrix has meaning like ✞ 1 ...*(*( ptr+i)+j).... ✌ ✆ Here, i is row number and j is column number, all started from zero to continue. 10 0 0 0 20 0 0 0 15 0 0 0 2 0 0 0 *(*(p)) *(*(p)+1) *(*(p+1)) *(*(p+1)+1) c1 c2 r1 r2 ✞ 1 #include stdio.h 3 int main () { int mat [3][3] = { 5 {11, 24, 53}, {45, 45, 64}, 7 {77, 87, 99}
  • 171. 2.2. POINTER 299 }; 9 printf(mat [0][0] element is = %dn ,*(*(mat +0) +0)); printf(mat [0][2] element is = %dn ,*(*(mat +0) +2)); 11 return 0; } ✌ ✆ ✞ mat [0][0] element is = 11 mat [0][2] element is = 53 ✌ ✆ Similarly, a three dimensional matrix has meaning like ✞ ...*(*(*( ptr+k)+i)+j).... ✌ ✆ Here, i is row number and j is column number and k is layer number, all started from zero to continue. ✞ 1 #include stdio.h 3 int main () { int mat[ ][2][3] = { 5 { {11, 24, 53}, 7 {45, 45, 64} }, 9 { {1, 2, 3}, 11 {5, 4, 6} } 13 }; /* First layer , first row first element */ 15 printf(mat [0][0][0] element is = %dn ,*(*(*( mat +0) +0) +0)); /* Second layer , second row first element */ 17 printf(mat [1][1][0] element is = %dn ,*(*(*( mat +1) +1) +0)); return 0; 19 } ✌ ✆ ✞ mat [0][0][0] element is = 11 mat [1][1][0] element is = 5 ✌ ✆ In the following example, a matrix array is passed to a array ‘ar’ of pointers to an integer and this array pointer is used to access the elements of the matrix. ✞ #include stdio.h 2 int main () { 4 int mat [3][3] = { {11, 24, 53}, 6 {45, 45, 64}, {77, 87, 99} 8 };
  • 172. 300 Array Pointer int (*a)[3]; 10 ar=mat; printf(ar [2][2] element is = %dn, *(*( ar +2) +2)); 12 printf(ar [0][2] element is = %dn, *(*( ar +0) +2)); return 0; 14 } ✌ ✆ ✞ mat [2][2] element is = 99 mat [0][2] element is = 53 ✌ ✆ ✞ #include stdio.h 2 int main () { 4 int Arr [3][3] = { {1, 2, 3}, 6 {4, 5, 6}, {7, 8, 9} 8 }; int (* mat)[3]; 10 mat = Arr; printf(Element at mat [0][1] = %dn, *(*( mat +0) +1)); 12 printf(8th element from positino of mat [0][0] = %dn, (*( mat + 0))[8]) ; 14 printf(6th element from position of mat [0][2] = %dn, (*( mat + 0) + 2) [6]) ; 16 return 0; } ✌ ✆ ✞ Element at mat [0][1] = 2 8th element from the position of mat [0][0] = 9 6th element from the position of mat [0][2] = 9 ✌ ✆ Following is an example in which a 3D matrix is accessed by using a pointer. ✞ 1 #include stdio.h 3 int main () { int Arr [3][3][3] = { 5 {/*[x][y] matrix with [z=0]*/ {11, 12, 13}, 7 {14, 15, 16}, {17, 18, 19} 9 }, {/*[x][y] matrix with [z=1]*/ 11 {21, 22, 23}, {24, 25, 26}, 13 {27, 28, 29} }, 15 {/*[x][y] matrix with [z=2]*/