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

PST Unit 5 Notes

Uploaded by

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

PST Unit 5 Notes

Uploaded by

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

C – Pointers

A pointer is a variable whose value is the address of another variable, i.e.,


direct address of the memory location. Like any variable or constant, you
must declare a pointer before using it to store any variable address. The
general form of a pointer variable declaration is −

type *var-name;

Here, type is the pointer's base type; it must be a valid C data type and var-
name is the name of the pointer variable. The asterisk * used to declare a
pointer is the same asterisk used for multiplication. However, in this
statement the asterisk is being used to designate a variable as a pointer.
Take a look at some of the valid pointer declarations −

int *ip; /* pointer to an integer */

double *dp; /* pointer to a double */

float *fp; /* pointer to a float */

char *ch /* pointer to a character */

The actual data type of the value of all pointers, whether integer, float,
character, or otherwise, is the same, a long hexadecimal number that
represents a memory address. The only difference between pointers of
different data types is the data type of the variable or constant that the
pointer points to.

How to Use Pointers?

There are a few important operations, which we will do with the help of
pointers very frequently. (a) We define a pointer variable, (b) assign the
address of a variable to a pointer and (c) finally access the value at the
address available in the pointer variable. This is done by using unary
operator * that returns the value of the variable located at the address
specified by its operand. The following example makes use of these
operations −
#include <stdio.h>

int main () {

int var = 20; /* actual variable declaration */

int *ip; /* pointer variable declaration */

ip = &var; /* store address of var in pointer variable*/

printf("Address of var variable: %x\n", &var );

/* address stored in pointer variable */

printf("Address stored in ip variable: %x\n", ip );

/* access the value using the pointer */

printf("Value of *ip variable: %d\n", *ip );

return 0;

When the above code is compiled and executed, it produces the following
result −

Address of var variable: bffd8b3c

Address stored in ip variable: bffd8b3c

Value of *ip variable: 20

NULL Pointers

It is always a good practice to assign a NULL value to a pointer variable in


case you do not have an exact address to be assigned. This is done at the
time of variable declaration. A pointer that is assigned NULL is called a null
pointer.

The NULL pointer is a constant with a value of zero defined in several


standard libraries. Consider the following program −

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

int *ptr = NULL;

printf("The value of ptr is : %x\n", ptr );

return 0;

When the above code is compiled and executed, it produces the following
result −

The value of ptr is 0

In most of the operating systems, programs are not permitted to access


memory at address 0 because that memory is reserved by the operating
system. However, the memory address 0 has special significance; it signals
that the pointer is not intended to point to an accessible memory location.
But by convention, if a pointer contains the null (zero) value, it is assumed to
point to nothing.

To check for a null pointer, you can use an 'if' statement as follows −

if(ptr) /* succeeds if p is not null */

if(!ptr) /* succeeds if p is null */

Passing pointers to functions


C programming allows passing a pointer to a function. To do so, simply
declare the function parameter as a pointer type.

Following is a simple example where we pass an unsigned long pointer to a


function and change the value inside the function which reflects back in the
calling function −

#include <stdio.h>

#include <time.h>

void getSeconds(unsigned long *par);

int main () {

unsigned long sec;

getSeconds( &sec );

/* print the actual value */

printf("Number of seconds: %ld\n", sec );

return 0;

void getSeconds(unsigned long *par) {

/* get the current number of seconds */

*par = time( NULL );

return;

When the above code is compiled and executed, it produces the following
result −

Number of seconds :1294450468

The function, which can accept a pointer, can also accept an array as shown
in the following example −
#include <stdio.h>

/* function declaration */

double getAverage(int *arr, int size);

int main () {

/* an int array with 5 elements */

int balance[5] = {1000, 2, 3, 17, 50};

double avg;

/* pass pointer to the array as an argument */

avg = getAverage( balance, 5 ) ;

/* output the returned value */

printf("Average value is: %f\n", avg );

return 0;

double getAverage(int *arr, int size) {

int i, sum = 0;

double avg;

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

sum += arr[i];

avg = (double)sum / size;

return avg;

}
When the above code is compiled together and executed, it produces the
following result −

Average value is: 214.40000

Operations on Pointers
A pointer in c is an address, which is a numeric value. Therefore, you can
perform arithmetic operations on a pointer just as you can on a numeric
value. There are four arithmetic operators that can be used on pointers: ++,
--, +, and -

To understand pointer arithmetic, let us consider that ptr is an integer


pointer which points to the address 1000. Assuming 32-bit integers, let us
perform the following arithmetic operation on the pointer −

ptr++

After the above operation, the ptr will point to the location 1004 because
each time ptr is incremented, it will point to the next integer location which
is 4 bytes next to the current location. This operation will move the pointer to
the next memory location without impacting the actual value at the memory
location. If ptr points to a character whose address is 1000, then the above
operation will point to the location 1001 because the next character will be
available at 1001.

Incrementing a Pointer

We prefer using a pointer in our program instead of an array because the


variable pointer can be incremented, unlike the array name which cannot be
incremented because it is a constant pointer. The following program
increments the variable pointer to access each succeeding element of the
array −

#include <stdio.h>

const int MAX = 3;

int main () {

int var[] = {10, 100, 200};

int i, *ptr;

/* let us have array address in pointer */

ptr = var;

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


{

printf("Address of var[%d] = %x\n", i, ptr );

printf("Value of var[%d] = %d\n", i, *ptr );

/* move to the next location */

ptr++;

return 0;

When the above code is compiled and executed, it produces the following
result −

Address of var[0] = bf882b30

Value of var[0] = 10

Address of var[1] = bf882b34

Value of var[1] = 100

Address of var[2] = bf882b38

Value of var[2] = 200

Decrementing a Pointer

The same considerations apply to decrementing a pointer, which decreases


its value by the number of bytes of its data type as shown below −

#include <stdio.h>

const int MAX = 3;

int main () {

int var[] = {10, 100, 200};

int i, *ptr;

/* let us have array address in pointer */

ptr = &var[MAX-1];
for ( i = MAX; i > 0; i--)

printf("Address of var[%d] = %x\n", i-1, ptr );

printf("Value of var[%d] = %d\n", i-1, *ptr );

/* move to the previous location */

ptr--;

return 0;

When the above code is compiled and executed, it produces the following
result −

Address of var[2] = bfedbcd8

Value of var[2] = 200

Address of var[1] = bfedbcd4

Value of var[1] = 100

Address of var[0] = bfedbcd0

Value of var[0] = 10

Pointer Comparisons
Pointers may be compared by using relational operators, such as ==, <, and
>. If p1 and p2 point to variables that are related to each other, such as
elements of the same array, then p1 and p2 can be meaningfully compared.

The following program modifies the previous example − one by incrementing


the variable pointer so long as the address to which it points is either less
than or equal to the address of the last element of the array, which is
&var[MAX - 1] −

#include <stdio.h>

const int MAX = 3;

int main () {

int var[] = {10, 100, 200};

int i, *ptr;

/* let us have address of the first element in pointer */

ptr = var;

i = 0;

while ( ptr <= &var[MAX - 1] ) {

printf("Address of var[%d] = %x\n", i, ptr );

printf("Value of var[%d] = %d\n", i, *ptr );

/* point to the previous location */

ptr++;

i++;

return 0;

When the above code is compiled and executed, it produces the following
result −

Address of var[0] = bfdbcb20


Value of var[0] = 10

Address of var[1] = bfdbcb24

Value of var[1] = 100

Address of var[2] = bfdbcb28

Value of var[2] = 200

Array of pointers
Before we understand the concept of arrays of pointers, let us consider the
following example, which uses an array of 3 integers −

#include <stdio.h>

const int MAX = 3;

int main ()

int var[] = {10, 100, 200};

int i;

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

printf("Value of var[%d] = %d\n", i, var[i] );

return 0;

When the above code is compiled and executed, it produces the following
result −

Value of var[0] = 10

Value of var[1] = 100

Value of var[2] = 200


There may be a situation when we want to maintain an array, which can
store pointers to an int or char or any other data type available. Following is
the declaration of an array of pointers to an integer −

int *ptr[MAX];

It declares ptr as an array of MAX integer pointers. Thus, each element in ptr,
holds a pointer to an int value. The following example uses three integers,
which are stored in an array of pointers, as follows −

#include <stdio.h>

const int MAX = 3;

int main () {

int var[] = {10, 100, 200};

int i, *ptr[MAX];

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

ptr[i] = &var[i]; /* assign the address of integer. */

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

printf("Value of var[%d] = %d\n", i, *ptr[i] );

return 0;

}
When the above code is compiled and executed, it produces the following
result −

Value of var[0] = 10

Value of var[1] = 100

Value of var[2] = 200

You can also use an array of pointers to character to store a list of strings as
follows −

#include <stdio.h>

const int MAX = 4;

int main () {

char *names[] = {

"Zara Ali",

"Hina Ali",

"Nuha Ali",

"Sara Ali"

};

int i = 0;

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

printf("Value of names[%d] = %s\n", i, names[i] );

return 0;

}
When the above code is compiled and executed, it produces the following
result −

Value of names[0] = Zara Ali

Value of names[1] = Hina Ali

Value of names[2] = Nuha Ali

Value of names[3] = Sara Ali

Structures and pointers


You can define pointers to structures in the same way as you define pointer
to any other variable −

struct Books *struct_pointer;

Now, you can store the address of a structure variable in the above defined
pointer variable. To find the address of a structure variable, place the '&';
operator before the structure's name as follows −

struct_pointer = &Book1;

To access the members of a structure using a pointer to that structure, you


must use the → operator as follows −

struct_pointer->title;

Let us re-write the above example using structure pointer.

#include <stdio.h>

#include <string.h>

struct Books {

char title[50];

char author[50];

char subject[100];

int book_id;

};

/* function declaration */
void printBook( struct Books *book );

int main( ) {

struct Books Book1; /* Declare Book1 of type Book */

struct Books Book2; /* Declare Book2 of type Book */

/* book 1 specification */

strcpy( Book1.title, "C Programming");

strcpy( Book1.author, "Nuha Ali");

strcpy( Book1.subject, "C Programming Tutorial");

Book1.book_id = 6495407;

/* book 2 specification */

strcpy( Book2.title, "Telecom Billing");

strcpy( Book2.author, "Zara Ali");

strcpy( Book2.subject, "Telecom Billing Tutorial");

Book2.book_id = 6495700;

/* print Book1 info by passing address of Book1 */

printBook( &Book1 );

/* print Book2 info by passing address of Book2 */

printBook( &Book2 );
return 0;

void printBook( struct Books *book )

printf( "Book title : %s\n", book->title);

printf( "Book author : %s\n", book->author);

printf( "Book subject : %s\n", book->subject);

printf( "Book book_id : %d\n", book->book_id);

When the above code is compiled and executed, it produces the following
result −

Book title : C Programming

Book author : Nuha Ali

Book subject : C Programming Tutorial

Book book_id : 6495407

Book title : Telecom Billing

Book author : Zara Ali

Book subject : Telecom Billing Tutorial

Book book_id : 6495700


Files in C

A file represents a sequence of bytes, regardless of it being a text file or a


binary file. C programming language provides access on high level functions
as well as low level (OS level) calls to handle file on your storage devices.
This chapter will take you through the important calls for file management.

Opening Files

You can use the fopen( ) function to create a new file or to open an existing
file. This call will initialize an object of the type FILE, which contains all the
information necessary to control the stream. The prototype of this function
call is as follows −

FILE *fopen( const char * filename, const char * mode );

Here, filename is a string literal, which you will use to name your file, and
access mode can have one of the following values −

Mode Description
R Opens an existing text file for reading
purpose.

W Opens a text file for writing. If it does


not exist, then a new file is
created. Here your program will start
writing content from the beginning of
the file.

a Opens a text file for writing in


appending mode. If it does not exist,
then a new file is created. Here your
program will start appending content
in the existing file content.

r+ both reading and writing Opens a


text file for.

w+ Opens a text file for both reading and


writing. It first truncates the file to
zero length if it exists, otherwise
creates a file if it does not exist.

a+ Opens a text file for both reading and


writing. It creates the file if it does
not exist. The reading will start from
the beginning but writing can only be
appended.
If you are going to handle binary files, then you will use following access
modes instead of the above mentioned ones −

"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"

Closing a File

To close a file, use the fclose( ) function. The prototype of this function is −

int fclose( FILE *fp );

The fclose(-) function returns zero on success, or EOF if there is an error in


closing the file. This function actually flushes any data still pending in the
buffer to the file, closes the file, and releases any memory used for the file.
The EOF is a constant defined in the header file stdio.h.

There are various functions provided by C standard library to read and write
a file, character by character, or in the form of a fixed length string.

Writing a File

Following is the simplest function to write individual characters to a stream −

int fputc( int c, FILE *fp );

The function fputc() writes the character value of the argument c to the
output stream referenced by fp. It returns the written character written on
success otherwise EOF if there is an error. You can use the following
functions to write a null-terminated string to a stream −

int fputs( const char *s, FILE *fp );

The function fputs() writes the string s to the output stream referenced by fp.
It returns a non-negative value on success, otherwise EOF is returned in case
of any error. You can use int fprintf(FILE *fp,const char *format, ...) function
as well to write a string into a file. Try the following example.
Make sure you have /tmp directory available. If it is not, then before
proceeding, you must create this directory on your machine.

#include <stdio.h>

main() {

FILE *fp;

fp = fopen("/tmp/test.txt", "w+");

fprintf(fp, "This is testing for fprintf...\n");

fputs("This is testing for fputs...\n", fp);

fclose(fp);

When the above code is compiled and executed, it creates a new file test.txt
in /tmp directory and writes two lines using two different functions. Let us
read this file in the next section.

Reading a File

Given below is the simplest function to read a single character from a file −

int fgetc( FILE * fp );

The fgetc() function reads a character from the input file referenced by fp.
The return value is the character read, or in case of any error, it returns EOF.
The following function allows to read a string from a stream −

char *fgets( char *buf, int n, FILE *fp );

The functions fgets() reads up to n-1 characters from the input stream
referenced by fp. It copies the read string into the buffer buf, appending a
null character to terminate the string.

If this function encounters a newline character '\n' or the end of the file EOF
before they have read the maximum number of characters, then it returns
only the characters read up to that point including the new line character.
You can also use int fscanf(FILE *fp, const char *format, ...) function to read
strings from a file, but it stops reading after encountering the first space
character.

#include <stdio.h>

main() {

FILE *fp;

char buff[255];

fp = fopen("/tmp/test.txt", "r");

fscanf(fp, "%s", buff);

printf("1 : %s\n", buff );

fgets(buff, 255, (FILE*)fp);

printf("2: %s\n", buff );

fgets(buff, 255, (FILE*)fp);

printf("3: %s\n", buff );

fclose(fp);

You might also like