0% found this document useful (0 votes)
14 views

PSC 2020 Lecture Notes Unit 4

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views

PSC 2020 Lecture Notes Unit 4

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 22

UNIT – IV

Pointer Variables:
Pointer:
A pointer variable is a variable that can store the address of another variable declared
for the same type. A variable is identified as pointer if it is preceded with the indirection
operator (*)
in the declaration.

Features of Pointers:
• Pointer saves the memory space.
• Execution speed increases by use of pointers.
• Dynamic memory allocation and de-allocation is possible
• Pointers are used with data structures.

Pointer Operators:

Pointer Declaration:
The general form for pointer declaration is given below:

Data type *variable;

Where data type can be any fundamental data type or user defined data type and the
variable name should follow the rules of identifier and * is called the indirection
operator or dereferencing operator.

For eg. int *x;


float *y;
char *z;
In the above example x is declared as integer pointer and it can store only the address
of another variable declared of type int.
In the above example y is declared as float pointer and it can store only the address
of another variable declared of type float.
In the above example z is declared as character pointer and it can store only the
address of another variable declared of type char.

Assigning address of another variable to pointer variable:

The general form for assigning the address of a variable to a pointer variable is given
below:
Pointer variable=&variable;
Where pointer variable and variable should be declared of the same type and & is the
reference or address operator.

Pointer Expressions/Arithmetic:
Arithmetic operations on pointers with using indirection operator:

Pointer variable used along with indirection operator other than the declaration
will be interpreted as value at address.

Below is given a simple example illustrating the usage of pointers in performing


arithmetic operations:

/* sample program to illustrate the use of pointers in performing arithmetic operations


*/
#include <stdio.h>
main()
{
Int a,b,res;
int *c,*d;
clrscr();
printf(“enter values for a and b:”);
scanf(“%d %d”,&a,&b);
c=&a; /* address of a assigned to c */
d=&b; /* address of b assigned to d */
res=*c + *d; /* pointer variable used with indirection operator that gives value at
address*/
printf(“sum of a and b is %d\n”,res);
}
Below is given a table that describes the contents of the variables for the above
program(Values and addresses of locations are assumed)
Name of the A B c(address) *c(value D *d(value at
variable at address)
Address)

Contents of 10 20 2050 10 3050 20


the
Variable
Address of the 2050 3050 2666 3666
variable

Explanation:
Value is read into the variable a and b through scanf statement and the address of the
variables are assigned to the pointer variables with the statements
c=&a;
d=&b;
The statement res=*c + *d , *c gives the value of the addressed location a and *d gives
the value of the addressed location b and these two values are added and the result
is stored in the variable res, which is then printed.

Note: if the pointer variable is prefixed with indirection operator and is used in any part
of the program other than the declaration, then it gives the value of the variable whose
address is assigned to this pointer variable.

If the pointer variable is not prefixed with indirection operator and is used inany part of
the program other than the declaration, then it gives the address of the variable whose
address is assigned to the pointer variable.

Arithmetic operations on pointers without using indirection operator:


Below is given a simple example illustrating the usage of pointers in performing
arithmetic operations:

Note: For pointer arithmetic, arithmetic operators * and / cannot be used.

/* sample program to illustrate the use of pointers in performing arithmetic operations


*/
#include <stdio.h>
main()
{
Int a,b;
int *c,*d;
clrscr();
a=5;
b=6;
c=&a; /* address of a assigned to c */
d=&b; /* address of b assigned to d */
c=c+2; /* use of pointer variable with no indirection operator */
printf(“value of c=%u\n”,c);
printf(“value of d=%u\n”,d);
}

Below is given a table that describes the contents of the variables for the above
program(Values and addresses of locations are assumed)
Name of the A B C(address) d C=c+2
variable
Contents of 5 6 2050 3050 2054
the variable
Address of 2050 3050 2666 3666 2666
the variable
Explanation:
In the arithmetic statement c=c+2, where pointer variable is used without indirection
operator then the statement computation is done as shown below:
c=c+2*No. of bytes allocated for that data type
as the pointer variable c holds the address of the variable a i.e., 2050 on substituting
this in the above statement, we get
c=2050+2*2
c=2054, similarly we perform for the next statement and the result is shown in the
table.

Pointers and Arrays:


Array name itself is an address or pointer. It points to the address of the first element
of the array. To understand this much better below we will see an example illustrating
this.

/* program to display the elements of the array using array as pointer and also to print
the
addresses of these locations. */
#include <stdio.h>
main()
{
Int num[5]={20,30,40,50,60};
Int i;
i=0;
while(i<5)
{
printf(“element=%3d address=%8u\n’,*(num+i),num+i);
i++;
}
}
Explanation:
If we suppose assume that the memory is allocated for the above declaration as shown

Num[0] Num[1] Num[2] Num[3] Num[4] Array


20 30 40 50 60 names
with index
3000 3002 3004 3006 3008
values
address

Multiple Indirection (pointer to pointer):

A pointer point to another pointer that points to the target value. This situation is called
multiple indirection, or pointer to pointer
A variable that is a pointer to a pointer must be declared as such. You do this by
placing an additional asterisk in front of the variable name. For example, the
following declaration tells the compiler that newbalance is a pointer to a pointer of
type float:

float **newbalance;
You should understand that newbalance is not a pointer to a floating-point
number but rather a pointer to a float pointer.

To access the target value indirectly pointed to by a pointer to a pointer, you must
apply the asterisk operator twice, as in this example:

#include <stdio.h>
int main(void)
{
int x, *p, **q;
x = 10;
p = &x;
q = &p;
printf("%d", **q); /* print the value of x */
return 0;
}
Here, p is declared as a pointer to an integer and q as a pointer to a pointer to an
integer. The call to printf( ) prints the number 10 on the screen.

Initializing Pointers:

A pointer that does not currently point to a valid memory location is given the value
null (which is zero). Null is used because C guarantees that no object will exist at the
null address. Thus, any
pointer that is null implies that it points to nothing and should not be used.

One way to give a pointer a null value is to assign zero to it. For example, the following
initializes p to null.
char *p = 0;

Additionally, many of C's headers, such as <stdio.h>, define the macro NULL, which
is a null
pointer constant. Therefore, you will often see a pointer assigned null using a
statement such as this:
p = NULL;

Pointers to Functions:
A function has a physical location in memory that can be assigned to a pointer. This
address is the entry point of the function and it is the address used when the function
is called. Once a pointer points to a function, the function can be called through that
pointer. Function pointers also allow functions to be passed as arguments to other
functions. You obtain the address of a function by using the function's name without
any parentheses or Arguments.

Arrays and Pointers

An array is a block of sequential data. Let's write a program to print addresses of array
elements.

#include <stdio.h>
int main() {
int x[4];
int i;

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


printf("&x[%d] = %p\n", i, &x[i]);
}

printf("Address of array x: %p", x);

return 0;
}

Output

&x[0] = 1450734448
&x[1] = 1450734452
&x[2] = 1450734456
&x[3] = 1450734460
Address of array x: 1450734448

There is a difference of 4 bytes between two consecutive elements of array x. It is


because the size of int is 4 bytes (on our compiler).
Notice that, the address of &x[0] and x is the same. It's because the variable
name x points to the first element of the array.
From the above example, it is clear that &x[0] is equivalent to x. And, x[0] is equivalent
to *x.
Similarly,

 &x[1] is equivalent to x+1 and x[1] is equivalent to *(x+1).


 &x[2] is equivalent to x+2 and x[2] is equivalent to *(x+2).
 ...

 Basically, &x[i] is equivalent to x+i and x[i] is equivalent to *(x+i).

Example 1: Pointers and Arrays

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

int i, x[6], sum = 0;

printf("Enter 6 numbers: ");


for(i = 0; i < 6; ++i) {
// Equivalent to scanf("%d", &x[i]);
scanf("%d", x+i);

// Equivalent to sum += x[i]


sum += *(x+i);
}

printf("Sum = %d", sum);

return 0;
}

When you run the program, the output will be:

Enter 6 numbers: 2
3
4
4
12
4
Sum = 29

Here, we have declared an array x of 6 elements. To access elements of the array,


we have used pointers.
In simple words, array names are converted to pointers. That's the reason why you
can use pointers to access elements of arrays. However, you should remember
that pointers and arrays are not the same.
Example 2: Arrays and Pointers

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

int x[5] = {1, 2, 3, 4, 5};


int* ptr;

// ptr is assigned the address of the third element


ptr = &x[2];

printf("*ptr = %d \n", *ptr); // 3


printf("*(ptr+1) = %d \n", *(ptr+1)); // 4
printf("*(ptr-1) = %d", *(ptr-1)); // 2

return 0;
}

When you run the program, the output will be:

*ptr = 3
*(ptr+1) = 4
*(ptr-1) = 2

In this example, &x[2], the address of the third element, is assigned to the ptr pointer.
Hence, 3 was displayed when we printed *ptr.
And, printing *(ptr+1) gives us the fourth element. Similarly, printing *(ptr-1) gives us
the second element.

Dynamic Memory Allocation


Memory allocated to variables at runtime is called dynamic memory
allocation. The programming language C supports functions for managing memory.
They are:

1. malloc()
2. calloc()
3. realloc()
4. free()

First three functions are used for allocating memory and the last function is
used to de-allocate the memory.

malloc()

The name "malloc" stands for memory allocation.

The malloc() function reserves a block of memory of the specified number of bytes.
And, it returns a pointer of void which can be casted into pointers of any form.
Syntax of malloc()

ptr = (castType*) malloc(size);

Example

ptr = (float*) malloc(100 * sizeof(float));

The above statement allocates 400 bytes of memory. It's because the size of float is
4 bytes. And, the pointer ptr holds the address of the first byte in the allocated memory.
The expression results in a NULL pointer if the memory cannot be allocated.

calloc()

The name "calloc" stands for contiguous allocation.

The malloc() function allocates memory and leaves the memory uninitialized, whereas
the calloc() function allocates memory and initializes all bits to zero.
Syntax of calloc()

ptr = (castType*)calloc(n, size);

Example:

ptr = (float*) calloc(25, sizeof(float));

The above statement allocates contiguous space in memory for 25 elements of


type float.
free()

Dynamically allocated memory created with either calloc() or malloc() doesn't get
freed on their own. You must explicitly use free() to release the space.
Syntax of free()

free(ptr);

This statement frees the space allocated in the memory pointed by ptr.

realloc()

If the dynamically allocated memory is insufficient or more than required, you can
change the size of previously allocated memory using the realloc() function.
Syntax of realloc()

ptr = realloc(ptr, x);

Here, ptr is reallocated with a new size x.


Example 3: realloc()

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

int main() {
int *ptr, i , n1, n2;
printf("Enter size: ");
scanf("%d", &n1);

ptr = (int*) malloc(n1 * sizeof(int));

printf("Addresses of previously allocated memory:\n");


for(i = 0; i < n1; ++i)
printf("%pc\n",ptr + i);

printf("\nEnter the new size: ");


scanf("%d", &n2);

// rellocating the memory


ptr = realloc(ptr, n2 * sizeof(int));
printf("Addresses of newly allocated memory:\n");
for(i = 0; i < n2; ++i)
printf("%pc\n", ptr + i);

free(ptr);

return 0;
}

Problems with Pointers:


 When a pointer is used incorrectly, or contains the wrong value, it will probably
cause your program to malfunction.
 The classic example of a pointer error is the uninitialized pointer.
 A second common error is caused by a simple misunderstanding of how to
use a pointer

Strings:

A string is a sequence of characters terminated with a null character \0. For example:

char c[] = "c string";

When the compiler encounters a sequence of characters enclosed in the double


quotation marks, it appends a null character \0 at the end by default.

How to declare a string?

Here's how you can declare strings:

char s[5];

String Declaration in C
Here, we have declared a string of 5 characters.

How to initialize strings?


You can initialize strings in a number of ways.

char c[] = "abcd";

char c[50] = "abcd";

char c[] = {'a', 'b', 'c', 'd', '\0'};

char c[5] = {'a', 'b', 'c', 'd', '\0'};

Assigning Values to Strings

Arrays and strings are second-class citizens in C; they do not support the assignment
operator once it is declared. For example,

char c[100];
c = "C programming"; // Error! array type is not assignable.

Read String from the user

You can use the scanf() function to read a string.


The scanf() function reads the sequence of characters until it
encounters whitespace (space, newline, tab, etc.).

Example 1: scanf() to read a string

#include <stdio.h>
int main()
{
char name[20];
printf("Enter name: ");
scanf("%s", name);
printf("Your name is %s.", name);
return 0;
}

How to read a line of text?

You can use the fgets() function to read a line of string. And, you can use puts() to
display the string.
Example 2: fgets() and puts()

#include <stdio.h>
int main()
{
char name[30];
printf("Enter name: ");
fgets(name, sizeof(name), stdin); // read string
printf("Name: ");
puts(name); // display string
return 0;
}

Output

Enter name: Tom Hanks


Name: Tom Hanks

Here, we have used fgets() function to read a string from the user.
fgets(name, sizeof(name), stdlin); // read string
The sizeof(name) results to 30. Hence, we can take a maximum of 30 characters as
input which is the size of the name string.
To print the string, we have used puts(name);.

Commonly Used String Functions

 strlen() - calculates the length of a string


 strcpy() - copies a string to another
 strcmp() - compares two strings
 strcat() - concatenates two strings

C strlen()

The strlen() function calculates the length of a given string.

The strlen() function takes a string as an argument and returns its length. The returned
value is of type size_t (the unsigned integer type).
It is defined in the <string.h> header file.

Example: C strlen() function

#include <stdio.h>
#include <string.h>
int main()
{
char a[20]="Program";
char b[20]={'P','r','o','g','r','a','m','\0'};

// using the %zu format specifier to print size_t


printf("Length of string a = %zu \n",strlen(a));
printf("Length of string b = %zu \n",strlen(b));

return 0;
}

Output

Length of string a = 7
Length of string b = 7

Note that the strlen() function doesn't count the null character \0 while calculating the
length.
C strcpy()

you will learn to use the strcpy() function in C programming to copy strings (with the
help of an example).

C strcpy()

The function prototype of strcpy() is:

char* strcpy(char* destination, const char* source);

 The strcpy() function copies the string pointed by source (including the null character)
to the destination.
 The strcpy() function also returns the copied string.
The strcpy() function is defined in the string.h header file.
Example: C strcpy()

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

int main() {
char str1[20] = "C programming";
char str2[20];

// copying str1 to str2


strcpy(str2, str1);

puts(str2); // C programming

return 0;
}

Output

C programming
Note: When you use strcpy(), the size of the destination string should be large enough
to store the copied string. Otherwise, it may result in undefined behavior.

C strcmp()

you will learn to compare two strings using the strcmp() function.

The strcmp() compares two strings character by character. If the strings are equal, the
function returns 0.

C strcmp() Prototype

The function prototype of strcmp() is:

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

strcmp() Parameters

The function takes two parameters:

 str1 - a string
 str2 - a string

Return Value from strcmp()


Return
Remarks
Value

0 if strings are equal

if the first non-matching character in str1 is greater (in ASCII) than


>0
that of str2.

if the first non-matching character in str1 is lower (in ASCII) than that
<0
of str2.

The strcmp() function is defined in the string.h header file.


Example: C strcmp() function

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

int main() {
char str1[] = "abcd", str2[] = "abCd", str3[] = "abcd";
int result;

// comparing strings str1 and str2


result = strcmp(str1, str2);
printf("strcmp(str1, str2) = %d\n", result);

// comparing strings str1 and str3


result = strcmp(str1, str3);
printf("strcmp(str1, str3) = %d\n", result);

return 0;
}

Output

strcmp(str1, str2) = 1

strcmp(str1, str3) = 0

In the program,
 strings str1 and str2 are not equal. Hence, the result is a non-zero integer.
 strings str1 and str3 are equal. Hence, the result is 0.

C strcat()

In C programming, the strcat() function concatenates (joins) two strings.

The function definition of strcat() is:

char *strcat(char *destination, const char *source)

It is defined in the string.h header file.

strcat() arguments

As you can see, the strcat() function takes two arguments:


destination - destination string
source - source string
The strcat() function concatenates the destination string and the source string, and
the result is stored in the destination string.
Example: C strcat() function

#include <stdio.h>
#include <string.h>
int main() {
char str1[100] = "This is ", str2[] = "programiz.com";

// concatenates str1 and str2


// the resultant string is stored in str1.
strcat(str1, str2);

puts(str1);
puts(str2);

return 0;
}

Output
This is programiz.com

programiz.com

Note: When we use strcat(), the size of the destination string should be large enough
to store the resultant string. If not, we will get the segmentation fault error.

Preprocessors:

The C preprocessor is a macro preprocessor (allows you to define macros) that


transforms your program before it is compiled. These transformations can be the
inclusion of header file, macro expansions etc.

All preprocessing directives begin with a # symbol. For example we will see the
following pre-processor directives

#include, #define and conditional compilation with the help of examples.

including Header Files: #include

The #include preprocessor is used to include header files to C programs. For example,

#include <stdio.h>

Here, stdio.h is a header file. The #include preprocessor directive replaces the above
line with the contents of stdio.h header file.
That's the reason why you need to use #include <stdio.h> before you can use
functions like scanf() and printf().
You can also create your own header file containing function declaration and include
it in your program using this preprocessor directive

#include "my_header.h"

Macros using #define

A macro is a fragment of code that is given a name. You can define a macro in C using
the #define preprocessor directive.
Here's an example.

#define c 299792458 // speed of light

Here, when we use c in our program, it is replaced with 299792458.


Example 1: #define preprocessor

#include <stdio.h>
#define PI 3.1415

int main()
{
float radius, area;
printf("Enter the radius: ");
scanf("%f", &radius);

// Notice, the use of PI


area = PI*radius*radius;

printf("Area=%.2f",area);
return 0;
}
Conditional Compilation

In C programming, you can instruct preprocessor whether to include a block of code


or not. To do so, conditional directives can be used.

It's similar to a if statement with one major difference.


The if statement is tested during the execution time to check whether a block of code
should be executed or not whereas, the conditionals are used to include (or skip) a
block of code in your program before execution.
Uses of Conditional

 use different code depending on the machine, operating system

 compile same source file in two different programs

 to exclude certain code from the program but to keep it as reference for future purpose

How to use conditional?

To use conditional, #ifdef, #if, #defined, #else and #elif directives are used.
#ifdef Directive

#ifdef MACRO
// conditional codes
#endif

Here, the conditional codes are included in the program only if MACRO is defined.

Important Questions:
1.Define Pointer. List the advantages and disadvantages of using pointers.
2. Briefly discuss the dynamic memory allocation functions supported in C.
3. With an example discuss the relationship between arrays and pointers.
4. Program in C to sort n elements using pointers.
5. Discuss the string handling functions supported in C.
6. Define a pre-processor. Discuss the pre-processor directives supported in C.
7. Write a program in C to sort strings using string handling functions.
8. How to identify a string and a character? Discuss.

Assignment Questions.

1. Briefly discuss the dynamic memory allocation functions supported in C.


2. Discuss the string handling functions supported in C.
3. Define a pre-processor. Discuss the pre-processor directives supported in C.

You might also like