Вы находитесь на странице: 1из 43

What is C language?

The C programming language is a standardized programming language developed in the early 1970s by Ken Thompson and Dennis Ritchie
for use on the UNIX operating system. C is the most popular programming language used for writing system software as well as for business
packages.
What are the features of C?
1.C
is
a
2.C
is
3.C is a middle-level language.
4.C uses the top-down approach
5.Programs written in C are efficient and fast.
6.C is highly portable language.

procedural-Oriented
a

programming
compiler-based

language

.
language.

Terminology:-

Character Set: A character denotes any alphabet, digit, white space or any special symbol that is used to represent information. A
character set is collection of characters.

Token: A token is the smallest individual unit of a program.

Instruction: An instruction is a statement that is given to computer to perform a specific operation.

Function: A function is a collection of instructions that performs a particular task.

Program: A program is a well-organized collection of instructions that is used to communicate with the computer system to accomplish
desired objective.

How many files are created when a C program is written using Borland c compiler?
When a C program is written, four files will be created:
1.
Source file (e.g., first.c)
2.

Back up file (e.g, first.bak)

3.

Object file (e.g., first.obj)

4.

Executable file (e.g., first.exe)

What are the steps in executing a C program?


Language processors are the system softwares that play key role in translating a source file into an executable file. These language processors
include: preprocessor, compiler, linker and loader. The translation process from source file into an executable file is depicted as follows:
1.
Entering a Program:- A text editor is used for this task. The statements written by the programmer are called source code and the
file in which the statements are saved is called as source file.
2.
Preprocessing:- During the first phase of this process, a program called the preprocessor reads the source code. The preprocessor
searches for special lines that begin with the # symbol. These lines (usually, called as preprocessor directives) contain commands that cause the
preprocessor to modify the source code in someway. The preprocessor modifies the existing source code and stores modified source code into
another file.
3.
Compiling:- During the next phase, the compiler steps through the preprocessed source code, translating each modified source
code instruction into the appropriate machine language instruction. This process will uncover any syntax error that may be in program. If the
program is free of syntax errors, the compiler stores the translated machine language instructions, which are called object code, in an object file.
4.
Linking:- During the last phase of the translation process, another program called the linker combines the object file with library
routines. Once the linker is finished with this step, an executable file is created. The executable file contains machine language instructions, or
executable code, and is ready to run on the computer.
5.
Loading:- Once, the executable file is stored on disk, the loader that is a part of operating system brings it to main memory and starts
it running.
This translation process is shown in the following figure:

What are the differences between break and exit() statements?


Break
1) It is used to come out of loop or switch or block in which it is
placed.
2) It is a keyword. Its definition has already defined by language
developers.

exit()
1) It is used to come out of entire program.
2) It is a pre-defined function that is available
inprocess.h or stdlib.h header files. It takes an argument: 0 or
1. exit(0) means a clean exit without an error message. exit(1) means
an abrupt exit with an error message.

When does the goto statement is used compulsary? Why should we avoid the use of goto statement?
goto statement is the best option when one wants the control jumps from inner most loop to outer most loop at once.
goto statement causes the loss of sequentiality in order of execution of instructions. Often, this leads us to difficulty in understanding the program.
Hence, it is suggested that one should avoid the use of goto statement.
Type Qualifiers:Type qualifiers are the keywords that add new meanings to existing data types. There are two type qualifiers: const,volatile.

Making a variable as read-only variable: In order to make the value of variable as unchanged during the execution of a program,
initialize the variable with the type qualifier const as follows:

Ex:

const

double

PI=3.1412;

This initialization tells the compiler that the value of PI must not be modified by the program. However, it can be used on the right hand side of
assignment
statement
like
other
variable.

Ex:
x=PI;

double

x;

Making a variable as modifiable externally: In order to make variables value modifiable at any time by some external sources (from
outside program), we use type qualifier volatile. For example,
volatile int

x;

The value of x may be altered by some external factors even if it does not appear on the left-hand side of an assignment statement. When we
declare a variable as volatile, the compiler will examine the value of the variable each time it is encountered to see whether any external alteration
has
changed
the
value.
Some

Interview

Questions:

1. What is Scope?
Scope refers to the visibility of a function or variable.
If the function or variable is visible outside of the current source file, it is said to have global, or external, scope.
If the function or variable is not visible outside of the current source file, it is said to have local, or static, scope.
2. What is modular programming?
If a program is large, it is subdivided into a number of smaller programs that are called modules or subprograms. If a complex problem is solved
using more modules, this approach is known as modular programming.
3. Is using exit() the same as using return?
No. The exit() function is used to exit your program and return control to the operating system. The return statement is used to return from a
function and return control to the calling function. If you issue a return from the main() function, you are essentially returning control to the calling
function, which is the operating system. In this case, the return
statement and exit() function are similar.
4. What is dangling else problem?
Dangling else problem is an ambiguous situation in which one can not judge the else statement to which if statement it belongs to. E.g., in the
above syntax, we can not judge the else statement whether it belongs to outer if statement or inner if statement.
In order to solve this problem, it is better to include the outer-if-body in curly braces. Hence, the above syntax can be redefined as:

5. What is a modulus operator? What are the restrictions of a modulus operator?


A Modulus operator gives the remainder value. The result of x%y is obtained by (x-(x/y)*y). This operator is applied only to integral operands and
cannot be applied to float or double.
6. Differentiate between a linker and linkage?
A linker converts an object code into an executable code by linking together the necessary build in functions. The form and place of declaration
where the variable is declared in a program determine the linkage of variable.
7. What is an argument? Differentiate between formal arguments and actual arguments?
An argument is an entity used to pass the data from calling function to the called function. Formal arguments are the arguments available in the
function definition. They are preceded by their own data types.
Actual arguments are available in the function call.
8. Can a variable be both const and volatile?
Yes. The const modifier means that this code cannot change the value of the variable, but that does not mean that the value cannot be changed
by means outside this code. Const is the qualifier that provides more data security by throwing error when an accidental attempt is made to
modify the same.However, the value can be changed by hardware on the computer, so it was declared volatile. If a variable is both const and
volatile, the two modifiers can appear in either order.

9.
What
are
There are 4 storage classes in C.
1.Auto
2. static
3.extern
4.

the

different

storage

classes

in

C?

register

Static-duration variables are allocated in main memory, usually along with the executable code of the program, and persist for the lifetime of the
program. Global variables (i.e, file scope) with or without the static specifier also have static scope.
Automatic-duration variables are allocated on the stack and come and go as functions are called and return. Variable having block scope and
without
static
specifier
have automatic
storage
duration.

Dynamic memory allocation in which memory is more explicitly (but more flexibly) managed, typically, by allocating it from the heap, an area of
memory structured for this purpose.
Register variables uses processor registers to store their contents if available. If not they will be converted to auto variables automatically.

10. What does static variable mean?


There are 3 main uses for the static.
1. If you declare within a function,it retains the value between function calls
2.If it is declared for a function name, it is invisible for the outer files.
(By default function is extern..so it will be visible from other files )
3. Static for global variables: that variable is limited to with in the file.
(By default we can use the global variables from outside files)

11. What are the differences between malloc() and calloc()?


There are 2 differences.
First, is in the number of arguments. malloc() takes a single argument(memory required in bytes), while calloc() needs 2 arguments(number of
variables to allocate memory, size in bytes of a single variable).
Secondly, malloc() does not initialize the memory allocated, while calloc() initializes the allocated memory to ZERO.
12. What is the difference between declaring a variable and defining a variable?
Declaring a variable means describing its type to the compiler but not allocating any space for it. Defining a variable means declaring it and also
allocating space to hold the variable. You can also initialize a variable at the time it is defined.
13. What is an lvalue?
An lvalue is an expression to which a value can be assigned. The lvalue expression is located on the left side of an assignment
statement,whereas an rvalue is located on the right side of an assignment statement. Each assignment statement must have an lvalue and an
rvalue. The lvalue expression must reference a storable variable in memory. It cannot be a constant.
14. Differentiate between an internal static and external static variable?
An internal static variable is declared inside a block with static storage class whereas an external static variable is declared outside all the blocks
in a file.An internal static variable has persistent storage,block scope and no linkage.An external static variable has permanent storage,file scope
and internal linkage.
15. When is a switch statement better than multiple if statements?
A switch statement is generally best to use when you have more than two conditional expressions based on a single variable of numeric type.
16. What is a static function?
A static function is a function whose scope is limited to the current source file. Scope refers to the visibility of a function or variable. If the function
or variable is visible outside of the current source file, it is said to have global, or external, scope. If the function or variable is not visible outside of
the current source file, it is said to have local, or static, scope.
17. What is a modulus operator? What are the restrictions of a modulus operator?
A Modulus operator gives the remainder value. The result of x%y is obtained by (x-(x/y)*y). This operator is applied only to integral operands and
cannot be applied to float or double.
18. Why should I prototype a function?
A function prototype tells the compiler what kind of arguments a function is looking to receive and what kind of return value a function is going to
give back. This approach helps the compiler ensure that calls to a function are made correctly and that no erroneous type
conversions are taking place.
Arrays
An array is finite homogeneous collection of elements stored in contiguous memory locations referred by same name.

This definition has the following parts:

Array consists of homogenous collection of elements. That is, all the data items stored in array are of same type.

All elements are stored in contiguous locations. That is, all elements are stored one after other in successive
locations of memory (based on size of type of data items). Of course, fixed amount of memory is allocated to an
array.
All elements refer to same name. That is, each element can be identified with the same name including different index value
(subscript value). Hence, an array is also called as a subscripted variable. By using, these index values, an element in the
array
can
be
accessed
directly.
Based on number of square brackets (subscripts or dimensions), arrays are broadly classified into two categories:
I.
II.

One-dimensional
Multi-dimensional

arrays.
arrays.

One-dimensional array consists of only one subscript. Multi-dimensional arrays consist of more than one subscript. E.g., twodimensional array consists of 2 subscripts; 3-dimensional array consists of 3 subscripts and so on. Usually, one-dimensional
numeric array consists of numbers as individual elements where as multi-dimensional numeric array consists of arrays as
individual
elements.
Hence,
multi-dimensional
array
is
also
called
as
array
of
arrays.
One-Dimensional

array:

Declaring
Just
like
an
ordinary
variable,
an
A one-dimensional array can be declared as follows:
$ < $storage class$ > $

$ < $data type$ > $

one-dimensional
array
should

be

declared

before

it

is

array:
used.

$ > $[size];

In this syntax, $ < $ storage class $ > $ is any one of auto, static, extern or register. It specifies the storage location of an
array,
the
default
values
of
all
elements,
scope
and
life
time
of
an
array.
$ < $ data type $ > $ is any basic data type such as int, float, char or double or any derived data type such as long int, short
int and so on.
$< $array_name$ > $ is any valid identifier.
Size is any non-negative integer constant or integer expression.

1.
2.

int

a[20];
float

//

one-dimensional
#
b[MAXSIZE];
//1-D

3.
int

c[k];

array

capable
define
array
capable
int
//Error:
Array

Initializing

of
of
size

holding
holding
cant

20
elements
MAXSIZE
30
elements
be

declared

one-dimensional

of
of
as

type

int
30
type
float
k=20;
a
variable.
array:

Initializing One-dimensional array is the process of assigning values to its all contiguous locations or to some of them with
some initial values for avoiding garbage values those are already in it. It can be directly done with the help of assignment
operator.
A one-dimensional array is initialized as follows: array declaration follows assignment operator and a list of values that are
separated by commas enclosed with in curly braces. This process is also called as initialization at compile-time.
Ex:

int

a[7]={12,45,54,2,87,76,3};

Once the above array gets initialized, the memory map for it will be as follows:

From this memory map, we can observe that an array subscript value (or index) starts from 0 and ends with n-1, where n is
the size of the array. Usually, the first elements location is called the base address of the array. Each element is uniquely
identified with the help of array name and its subscript value 1 or base address+ (pos-1) * sizeof(type). . e.g., 4th element
of
array
a
is
identified
with
a[3]
or
1000+(4-1)*2=1006.
Reading

and

printing

one-dimensional

array:

A One-Dimensional arrays locations can be filled with input values from keyboard with the help of scanf() statement. Because
an array consists of more than one element, we should require a loop counter for keeping track of index values. The loop
counter is always an integer value that begins with 0 and ends with n-1. The loop counter should be incremented by 1 for
keeping track of next immediate indexes. For each indexed element, scanf() statement expects an input value from
programmer.
This
process
can
be
depicted
with
the
help
of
the
following
statement:
for(i=0;i$

<

$;i++)

scanf(%d,&a[i]);
The above statement first reads a[0], then a[1], a[2], a[3]and so on. This process is also called as initialization at run-time.
Once an array is read, it can be accessed directly or sequentially with the help of printf() statement. If we want an element at
particular
position,
then
we
should
give
the
following
argument
to
printf()
:
a[position-1].
E.g.,

we

want

the

element

at

5th

position,

then

printf(Element

we

should

at

5th

give

a[4]

to

position

printf()

statement:

is

%d,a[4]);

If we want to access all the elements in the array sequentially, then we can use printf() statement along with a loop as follows:
printf(\n

The
for(i=0;i$

array

elements
>

Two-Dimensional

are:);
$n;i++)
printf(%d\t,a[i]);
arrays:

A Two-Dimensional array looks like array name followed by two subscripts. It is very helpful to represent matrices in
mathematics or tables in business. The first subscript is used to denote the Number of rows and second is used to denote the
number of columns. The total number of elements a two-dimensional array holds is the product of values of both subscript
values.
Declaring

Two-Dimensional

array:

Just like an ordinary variable, an array should be declared before it is used. A two-dimensional array can be declared as
follows:

$ < $data type$ > $ $ < $array_name$ > $[row][column];

In
this
syntax,
is any basic data type such as int, float, char or double or any derived data type such as long int, short int and so on.
$ < $data type$ > $ is any basic data type such as int, float, char or double or any derived data type such as long int, short int
and so on.
$ < $array_name$ > $ is any valid identifier.
row
Ex:

float

and
column
values
are
any
non-negative
integer
constants
or
integer
expressions.
int
a[5][3];
//
two-dimensional
array
capable
of
holding
15
(5*3)
elements
of
type
int
#
define
ROW
10
#
define
COLUMN
5
b[ROW][COLUMN];
//2-D
array
capable
of
holding
15
elements
of
type
float

Initializing

Two-Dimensional

array:

Initializing Two-dimensional array is the process of assigning values to its all contiguous locations or to some of them with
some initial values for avoiding garbage values those are already in it. It can be directly done with the help of assignment
operator.
A Two-dimensional array is initialized as follows: array declaration follows assignment operator and a list of values that are
separated
by
commas
enclosed
with
in
curly
braces.
Ex:
int
a[3][4]={{12,45,54,2},{87,76,3,4},{54,64,34,23}};
Once the above array gets initialized, the values will be stored in memory. The following memory map depicts this thing:
From this memory map, we can observe that a Two-Dimensional arrays rows subscript value as well as columns subscripts
value
start
from
0
and
end
with
n-1.
Reading

and

printing

Two-Dimensional

array:

A Two-Dimensional arrays locations can be filled with input values from keyboard with the help of scanf() statement. Because
an array consists of more than one element, we should require loop counters for keeping track of index values for both rows
and columns. The loop counters are always integer values those begin with 0 and ends with n-1. The loop counters should be

incremented by 1 for keeping track of next immediate indexes. For each indexed element, scanf() statement expects an input
value from programmer. This process can be depicted with the help of the following statement:
for(i=0;i$ < $m;i++)
// m: No.of rows i: loop counter for rows
for(j=0;j$ < $n;j++)
// n: No.of columns j: loop counter for columns
scanf(%d,&a[i][j]);
The
above
statement
first
reads
a[0][0],
then
a[0][1],
a[0][2],
a[0][3]and
so
on.
Once an array is read, it can be accessed directly or sequentially with the help of printf() statement. If we want an element at
particular position, then we should give the following argument to printf() : a[row-1][column-1]. E.g., we want the element at
3rd
row
and
2nd
column
position,
then
we
should
give
a[2][1]
to
printf()
statement:
printf(Element
at
3rd
row
and
2nd
column
position
is
%d,a[2][1]);
We can access all the elements in the array sequentially. For this, we use printf() statement along with two loops as follows:
printf(\n The array elements are:);
for(i=0;i$ < $m;i++)
for(j=0;j$ < $n;j++)
printf(%d\t,a[i][j]);

Pointers

A Pointer is a special type of variable that holds the address as a data item in it. The address may be of one of these: variable, array, function, structure or another pointer.

Usually, an ordinary variable holds a number or a character as a data item in it. Instead, pointer holds the address. If a variable occupies more than one byte, pointer holds the first byte

(or byte0) address. As this is a variable, the address in a pointer can be changed. Mostly, pointer uses 2 or 4 bytes to hold the addresses. In short, a pointer variable is a group of cells

that can hold an address.

Pointer is an address; not any ordinary value

Advantages of pointers

Pointers are used frequently in C, as they offer a number of benefits to the programmers. These include:

Pointers can be used to access and manipulate data stored in memory directly.

Pointers allow C to support dynamic memory allocation.

Pointers provide an efficient way to create and manipulate efficient data structures such as stacks, queues, linked lists, trees and graphs.

Pointers increase the execution speed and thus reduce the programs execution time.

Pointers are more efficient in handling arrays and data tables.

The use of pointer arrays to strings results in saving of data storage space in memory.

Pointers allow to change the calling functions arguments and to return multiple values from called function.

Pointers permit references to functions and thereby facilitating passing of functions as arguments to other functions.

The real power of C lies in the proper use of pointers. The misuse of pointers causes serious problems such as system crash.

11.3. Referencing operator (&)

Referencing operator is a unary operator. It acts on one operand at a time. It returns the address of operand. The operand must be a named region of storage (like int variable, array

variable, pointer variable etc.) for which a value may be assigned. The operand must not be a constant or an expression or a register variable. This operator is also called as address of

operator.

The & operator should be preceded with the operand in order to return the address.

Valid expressions:

&a

&c

//where a is the name of variable.

//where c is the name of an array.

&fact //where fact is the name of function.

Invalid expressions: &253 //constant cant be used as an operand.

&(a+b) //expression cant be used as an operand.

&r //register type cant be used as an operand.

Consider the declaration:

int a=20;

This declaration tells the C compiler to:

a) Reserve the required space in memory to hold the integer value.

b) Associate the name a with this memory location.

c) Store the value 20 at this location.

Suppose that the variable a occupies 2 bytes on 16-bit computer. This can be represented as follows:

From this memory map, it is clear that the data item 20 can be accessed with the help of name of variable as well as address of variable (or memory location or reference).

The conversion character %x is used to print address in hexa-decimal notation. The conversion character %u is used to print the address in decimal notation (especially, a positive

number to understand easily).

Program to print the address of variable in hexa decimal and decimal notations

#include

main()

int a=20;

printf(\n The address of a =%x,&a); //prints address in hexa decimal notation

printf(\n The address of a=%u,&a); // prints the address as a positive long integer

Dereferencing operator (*)

Dereferencing operator is a unary operator. It acts on one operand at a time. It returns the value stored at the address of operand. The operand must be an address, a pointer that holds

address or a pointer expression. This operator is also called as value at address operator or indirection operator.

The * operator should be preceded with the operand in order to return the value at address of operand.

Valid expressions: $*(\& $num) //where num is a variable

$*\& *\& $num

$**\& $num

Invalid expressions:

*2009

//constant value cant be used as an operand.

*num

//only addresses or pointers or pointer expressions can be used.

($*\& $)num //parentheses should not enclose two unary operators

Working with pointers:

In order to work with pointers, do the following:

1. Declare a pointer variable

2. Initialize it.

3. Access the original value through a pointer or perform any other operation on it.

Declaration of a pointer variable: Just like an ordinary variable, a pointer variable should be declared before it is used. This declaration has the following form:

In this syntax,

$ < $storage_class$ > $ is any one of the auto, static, extern or register.

$ < $data typte$ > $ is any one of int, float, char, double or void or data types such as signed int, long int etc,
The symbol * should be preceded with the name(s) of pointer(s).

<$ < $pointer_name$ > $ is any valid identifier. If there are more pointer_names, those should be separated with commas.
Ex:
int *iptr;
//pointer-to-int
float *fptr; //pointer-to-float
char *cptr; //pointer-to-char
The declaration int *iptr; does not mean that iptr is going to contain integer value. What it means is, iptr is a pointer variable that is going to hold the address of an integer value.
Hence, iptr is a pointer that points to integer value. In short, iptr is a pointer-to-int.
In the same way, the pointer fptr is going to contain the address of floating point value. Hence, fptr is a pointer that points to a floating point value. In short, fptr is a pointer-tofloat.
Similarly, the pointer cptr is going to contain the address of a character. Hence, cptr is a pointer that points to a character. In short, cptr is a pointer-to-char.
Initialization of a pointer variable: A pointer variable should be initialized with an address before it is used. The initialization of a pointer variable takes the following form:

Where Lvalue is any pointer variable and Rvalue is a variable preceded with an ampersand or a pointer of same type of LValue.

Ex:

int a=40;
int *iptr1,*iptr2;
//Declaring pointer variables: iptr1,iptr2
iptr1=&a;
//Initializing pointer variable: iptr1
iptr2=iptr1;
//Initializing pointer variable: iptr2
Whenever a pointer variable is initialized with the address of an ordinary variable or a pointer variable, we can say that the pointer variable points to that ordinary variable or pointer
variable. This can be represented as follows:

Accessing a pointer variable:

Once a pointer variable is initialized, it can be used to access the address as well as content of object to which it is pointed to. The following program demonstrates this:

Program to declare, initialize and access a pointer variable:

#include$ < $stdio.h$ > $

main()

int a=40;

int *iptr;

//Declaration: pointer-to-int

iptr=&a;

//Initialization: with the address of a

printf(\n The address of a=%u,&a);

printf(\n The address of a=%u,iptr); //accessed to print address of a

printf(\n The value of a=%d,a);

printf(\n The value of a=%d,*(&a));

printf(\n The value of a=%d,*iptr); //accessed to print the content of a

}
Operations on pointers:
Pointer arithmetic

The following arithmetic operations can be performed on pointers:


Addition of a number to a pointer.

Subtraction of a number from a pointer.

Subtraction of a pointer from another pointer.

The following arithmetic operations can not be performed on pointers:

Addition, multiplication, division and modulo division of two pointers.


Multiplication, division and modulo division of a pointer by a number.
Shifting operations.
Pointer increment and decrement:

Pointer
Expression
Ptr+n
Ptr-n
Ptr++

Description
Ptr=Ptr+n*sizeof(data_type_of_pointer)
Use the original value of ptr and then n*sizeof(data_type_of_pointer) is
added to ptr after statement execution.
Ptr=Ptr-n*sizeof(data_type_of_pointer)
Use the original value of ptr and then n*sizeof(data_type_of_pointer) is
subtracted from ptr after statement execution.
Ptr=Ptr+ sizeof(data_type_of_pointer)
Use the original value of ptr and then ptr is incremented after statement

Ptr-++Ptr
--Ptr
*Ptr++
*Ptr-*++Ptr
*--Ptr
(*Ptr)++
(*Ptr)--

execution.
Ptr=Ptr- sizeof(data_type_of_pointer)
Use the original value of ptr and then ptr is decremented after statement
execution.
Ptr=Ptr+ sizeof(data_type_of_pointer)
Original Ptr is incremented before the execution of statement.
Ptr=Ptr- sizeof(data_type_of_pointer)
Original Ptr is decremented before the execution of statement.
*(Ptr++)
Retrieve the content of the location pointed to by pointer and then
increment ptr.
*(Ptr--)
Retrieve the content of the location pointed to by pointer and then
decrement ptr.
*(++ptr)
Increment pointer and then retrieve the content of the new location
pointed to by Ptr.
*(--Ptr)
Decrement pointer and then retrieve the content of the new location
pointer to by Ptr.
Retrieve the content of *Ptr of the location pointed to by Ptr, and then
Increment content of the location pointed to by Ptr. For pointer type
content, use pointer arithmetic of standard arithmetic.
Retrieve the content *Ptr of the location pointed to by Ptr, then decrement
the content of that location; Ptr is not changed.

Pointer comparisons:

Two pointers can be compared by using relational operators as well as logical operators. When these operators encountered, these expressions may return either true or false. program

to demonstrate pointer comparisons

#include$ < $stdio.h$ < $

main()

int a=40,b=34;

int *iptr1,*iptr2;

iptr1=&a;

iptr2=&b;

printf(\n Equal condition of two pointers=%d,(ip1==ip2));

printf(\n Not Equal condition of two pointers=%d,(ip1!=ip2));

printf(\n Greater than condition of two pointers=%d,(ip1>ip2));

printf(\n Lesser than condition of two pointers=%d,(ip1

printf(\n Greater than or equals condition of two pointers=%d,(ip1>=ip2));

printf(\n Lesser than or equals condition of two pointers=%d,(ip1<=ip2));

printf(\n Logical AND condition of two pointers=%d,( ip1>=ip2&&ip1==ip2));

printf(\n Logical OR condition of two pointers=%d,(ip1==ip2|| ip1

printf(\n Logical NOT condition of two pointers=%d,(!(ip1==ip2)));

* Comparing two pointers those point to different types of objects lead to error, although they have addresses as data items in them.

Various pointer declarations:

Declare a variable of type float?

float x;

Declare an array that holds 10 floating-point values?

float a[10];

Declare a function that takes a character as argument and returns a character as return value?

char fun(char);

Declare a pointer-to-float?

float *fptr;

Declare a function that returns a pointer-to-float?

float * fun(void);

Declare a pointer-to-function that takes a double argument and returns a double value?

double (*fun)(double);

Declare a pointer-to-10-integer element array?

int (*arrptr)[10];

Declare an array of integer pointers of size 10?

int *a[10];

Declare a pointer to char?

char *cptr;

Declare a pointer-to-pointer to a char?

char **cptr;

Declare a pointer-to-pointer-to-pointer to a char?

char ***cptr;

Declare a function that returns a pointer to the array of floats?

float (*fun())[10];

Declare an array of pointers to a function returning float?

float (*f[10])();

Problems with pointers:

1) Segmentation fault (or segfault):

This generally means that a program tried to access the memory it shouldnt have, invariably as a result of improper pointer use. The most likely causes could be inadvertent use of null
pointers or uninitialized, misaligned, or otherwise improperly allocated pointers, corruption of malloc area and mismatched function arguments, especially involving pointers; two possible
cases are scanf(%d,i) (without ampersand) and fprintf(invalid FILE* argument).
A segmentation fault occurs when an attempt is made to access memory whose address is well-formed, but to which access cant be granted. This might be due to either a
protection fault or an invalid page fault.

2) Un-initialized pointer:

This generally occurs when we declared a pointer, forgot to initialize it with an address and tried to access the content through pointer. E.g.,
int *ptr, val=300;
*ptr=val; /*Error*/
3) When we want to assign a value to a pointer variable, then that assignment leads to an error.
E.g.,
int *p, val=24;
p=val; /*Error*/
4) When we want to assign the address of un-initialized variable to a pointer, then that assignment also leads to an error.
E.g., int val,*ptr;
ptr=&val; /*Error*/
5) When we want to compare pointers those point to different objects, that comparison lead to an error
E.g., char name1[20],name2[20];
char *p1=name1;
char *p2=name2;
if(p1>p2).
/*Error*/

Pointers

A Pointer is a special type of variable that holds the address as a data item in it. The address may be of one of these: variable, array, function, structure or another pointer.

Usually, an ordinary variable holds a number or a character as a data item in it. Instead, pointer holds the address. If a variable occupies more than one byte, pointer holds the first byte

(or byte0) address. As this is a variable, the address in a pointer can be changed. Mostly, pointer uses 2 or 4 bytes to hold the addresses. In short, a pointer variable is a group of cells

that can hold an address.

Pointer is an address; not any ordinary value

Advantages of pointers

Pointers are used frequently in C, as they offer a number of benefits to the programmers. These include:

Pointers can be used to access and manipulate data stored in memory directly.

Pointers allow C to support dynamic memory allocation.

Pointers provide an efficient way to create and manipulate efficient data structures such as stacks, queues, linked lists, trees and graphs.

Pointers increase the execution speed and thus reduce the programs execution time.

Pointers are more efficient in handling arrays and data tables.

The use of pointer arrays to strings results in saving of data storage space in memory.

Pointers allow to change the calling functions arguments and to return multiple values from called function.

Pointers permit references to functions and thereby facilitating passing of functions as arguments to other functions.

The real power of C lies in the proper use of pointers. The misuse of pointers causes serious problems such as system crash.

11.3. Referencing operator (&)

Referencing operator is a unary operator. It acts on one operand at a time. It returns the address of operand. The operand must be a named region of storage (like int variable, array

variable, pointer variable etc.) for which a value may be assigned. The operand must not be a constant or an expression or a register variable. This operator is also called as address of

operator.

The & operator should be preceded with the operand in order to return the address.

Valid expressions:

&a

&c

//where a is the name of variable.

//where c is the name of an array.

&fact //where fact is the name of function.

Invalid expressions: &253 //constant cant be used as an operand.

&(a+b) //expression cant be used as an operand.

&r //register type cant be used as an operand.

Consider the declaration:

int a=20;

This declaration tells the C compiler to:

a) Reserve the required space in memory to hold the integer value.

b) Associate the name a with this memory location.

c) Store the value 20 at this location.

Suppose that the variable a occupies 2 bytes on 16-bit computer. This can be represented as follows:

From this memory map, it is clear that the data item 20 can be accessed with the help of name of variable as well as address of variable (or memory location or reference).

The conversion character %x is used to print address in hexa-decimal notation. The conversion character %u is used to print the address in decimal notation (especially, a positive

number to understand easily).

Program to print the address of variable in hexa decimal and decimal notations

#include

main()

int a=20;

printf(\n The address of a =%x,&a); //prints address in hexa decimal notation

printf(\n The address of a=%u,&a); // prints the address as a positive long integer

Dereferencing operator (*)

Dereferencing operator is a unary operator. It acts on one operand at a time. It returns the value stored at the address of operand. The operand must be an address, a pointer that holds

address or a pointer expression. This operator is also called as value at address operator or indirection operator.

The * operator should be preceded with the operand in order to return the value at address of operand.

Valid expressions: $*(\& $num) //where num is a variable

$*\& *\& $num

$**\& $num

Invalid expressions:

*2009

//constant value cant be used as an operand.

*num

//only addresses or pointers or pointer expressions can be used.

($*\& $)num //parentheses should not enclose two unary operators

Working with pointers:

In order to work with pointers, do the following:

1. Declare a pointer variable

2. Initialize it.

3. Access the original value through a pointer or perform any other operation on it.

Declaration of a pointer variable: Just like an ordinary variable, a pointer variable should be declared before it is used. This declaration has the following form:

In this syntax,

$ < $storage_class$ > $ is any one of the auto, static, extern or register.

$ < $data typte$ > $ is any one of int, float, char, double or void or data types such as signed int, long int etc,
The symbol * should be preceded with the name(s) of pointer(s).

<$ < $pointer_name$ > $ is any valid identifier. If there are more pointer_names, those should be separated with commas.
Ex:
int *iptr;
//pointer-to-int
float *fptr; //pointer-to-float
char *cptr; //pointer-to-char
The declaration int *iptr; does not mean that iptr is going to contain integer value. What it means is, iptr is a pointer variable that is going to hold the address of an integer value.
Hence, iptr is a pointer that points to integer value. In short, iptr is a pointer-to-int.
In the same way, the pointer fptr is going to contain the address of floating point value. Hence, fptr is a pointer that points to a floating point value. In short, fptr is a pointer-tofloat.
Similarly, the pointer cptr is going to contain the address of a character. Hence, cptr is a pointer that points to a character. In short, cptr is a pointer-to-char.
Initialization of a pointer variable: A pointer variable should be initialized with an address before it is used. The initialization of a pointer variable takes the following form:

Where Lvalue is any pointer variable and Rvalue is a variable preceded with an ampersand or a pointer of same type of LValue.

Ex:

int a=40;
int *iptr1,*iptr2;
//Declaring pointer variables: iptr1,iptr2
iptr1=&a;
//Initializing pointer variable: iptr1
iptr2=iptr1;
//Initializing pointer variable: iptr2
Whenever a pointer variable is initialized with the address of an ordinary variable or a pointer variable, we can say that the pointer variable points to that ordinary variable or pointer
variable. This can be represented as follows:

Accessing a pointer variable:


Once a pointer variable is initialized, it can be used to access the address as well as content of object to which it is pointed to. The following program demonstrates this:

Program to declare, initialize and access a pointer variable:

#include$ < $stdio.h$ > $

main()

int a=40;

int *iptr;

//Declaration: pointer-to-int

iptr=&a;

//Initialization: with the address of a

printf(\n The address of a=%u,&a);

printf(\n The address of a=%u,iptr); //accessed to print address of a

printf(\n The value of a=%d,a);

printf(\n The value of a=%d,*(&a));

printf(\n The value of a=%d,*iptr); //accessed to print the content of a

}
Operations on pointers:
Pointer arithmetic

The following arithmetic operations can be performed on pointers:


Addition of a number to a pointer.
Subtraction of a number from a pointer.

Subtraction of a pointer from another pointer.

The following arithmetic operations can not be performed on pointers:

Addition, multiplication, division and modulo division of two pointers.


Multiplication, division and modulo division of a pointer by a number.
Shifting operations.
Pointer increment and decrement:

Pointer
Expression
Ptr+n
Ptr-n
Ptr++
Ptr-++Ptr
--Ptr
*Ptr++
*Ptr-*++Ptr
*--Ptr
(*Ptr)++
(*Ptr)--

Description
Ptr=Ptr+n*sizeof(data_type_of_pointer)
Use the original value of ptr and then n*sizeof(data_type_of_pointer) is
added to ptr after statement execution.
Ptr=Ptr-n*sizeof(data_type_of_pointer)
Use the original value of ptr and then n*sizeof(data_type_of_pointer) is
subtracted from ptr after statement execution.
Ptr=Ptr+ sizeof(data_type_of_pointer)
Use the original value of ptr and then ptr is incremented after statement
execution.
Ptr=Ptr- sizeof(data_type_of_pointer)
Use the original value of ptr and then ptr is decremented after statement
execution.
Ptr=Ptr+ sizeof(data_type_of_pointer)
Original Ptr is incremented before the execution of statement.
Ptr=Ptr- sizeof(data_type_of_pointer)
Original Ptr is decremented before the execution of statement.
*(Ptr++)
Retrieve the content of the location pointed to by pointer and then
increment ptr.
*(Ptr--)
Retrieve the content of the location pointed to by pointer and then
decrement ptr.
*(++ptr)
Increment pointer and then retrieve the content of the new location
pointed to by Ptr.
*(--Ptr)
Decrement pointer and then retrieve the content of the new location
pointer to by Ptr.
Retrieve the content of *Ptr of the location pointed to by Ptr, and then
Increment content of the location pointed to by Ptr. For pointer type
content, use pointer arithmetic of standard arithmetic.
Retrieve the content *Ptr of the location pointed to by Ptr, then decrement
the content of that location; Ptr is not changed.

Pointer comparisons:

Two pointers can be compared by using relational operators as well as logical operators. When these operators encountered, these expressions may return either true or false. program

to demonstrate pointer comparisons

#include$ < $stdio.h$ < $

main()

int a=40,b=34;

int *iptr1,*iptr2;

iptr1=&a;

iptr2=&b;

printf(\n Equal condition of two pointers=%d,(ip1==ip2));

printf(\n Not Equal condition of two pointers=%d,(ip1!=ip2));

printf(\n Greater than condition of two pointers=%d,(ip1>ip2));

printf(\n Lesser than condition of two pointers=%d,(ip1

printf(\n Greater than or equals condition of two pointers=%d,(ip1>=ip2));

printf(\n Lesser than or equals condition of two pointers=%d,(ip1<=ip2));

printf(\n Logical AND condition of two pointers=%d,( ip1>=ip2&&ip1==ip2));

printf(\n Logical OR condition of two pointers=%d,(ip1==ip2|| ip1

printf(\n Logical NOT condition of two pointers=%d,(!(ip1==ip2)));

* Comparing two pointers those point to different types of objects lead to error, although they have addresses as data items in them.

Various pointer declarations:

Declare a variable of type float?

float x;

Declare an array that holds 10 floating-point values?

float a[10];

Declare a function that takes a character as argument and returns a character as return value?

char fun(char);

Declare a pointer-to-float?

float *fptr;

Declare a function that returns a pointer-to-float?

float * fun(void);

Declare a pointer-to-function that takes a double argument and returns a double value?

double (*fun)(double);

Declare a pointer-to-10-integer element array?

int (*arrptr)[10];

Declare an array of integer pointers of size 10?

int *a[10];

Declare a pointer to char?

char *cptr;

Declare a pointer-to-pointer to a char?

char **cptr;

Declare a pointer-to-pointer-to-pointer to a char?

char ***cptr;

Declare a function that returns a pointer to the array of floats?

float (*fun())[10];

Declare an array of pointers to a function returning float?

float (*f[10])();

Problems with pointers:

1) Segmentation fault (or segfault):

This generally means that a program tried to access the memory it shouldnt have, invariably as a result of improper pointer use. The most likely causes could be inadvertent use of null
pointers or uninitialized, misaligned, or otherwise improperly allocated pointers, corruption of malloc area and mismatched function arguments, especially involving pointers; two possible
cases are scanf(%d,i) (without ampersand) and fprintf(invalid FILE* argument).
A segmentation fault occurs when an attempt is made to access memory whose address is well-formed, but to which access cant be granted. This might be due to either a
protection fault or an invalid page fault.

2) Un-initialized pointer:

This generally occurs when we declared a pointer, forgot to initialize it with an address and tried to access the content through pointer. E.g.,
int *ptr, val=300;
*ptr=val; /*Error*/
3) When we want to assign a value to a pointer variable, then that assignment leads to an error.
E.g.,
int *p, val=24;
p=val; /*Error*/
4) When we want to assign the address of un-initialized variable to a pointer, then that assignment also leads to an error.
E.g., int val,*ptr;
ptr=&val; /*Error*/
5) When we want to compare pointers those point to different objects, that comparison lead to an error
E.g., char name1[20],name2[20];
char *p1=name1;
char *p2=name2;
if(p1>p2).
/*Error*/

Pointers

A Pointer is a special type of variable that holds the address as a data item in it. The address may be of one of these: variable, array, function, structure or another pointer.

Usually, an ordinary variable holds a number or a character as a data item in it. Instead, pointer holds the address. If a variable occupies more than one byte, pointer holds the first byte

(or byte0) address. As this is a variable, the address in a pointer can be changed. Mostly, pointer uses 2 or 4 bytes to hold the addresses. In short, a pointer variable is a group of cells

that can hold an address.

Pointer is an address; not any ordinary value

Advantages of pointers

Pointers are used frequently in C, as they offer a number of benefits to the programmers. These include:

Pointers can be used to access and manipulate data stored in memory directly.

Pointers allow C to support dynamic memory allocation.

Pointers provide an efficient way to create and manipulate efficient data structures such as stacks, queues, linked lists, trees and graphs.

Pointers increase the execution speed and thus reduce the programs execution time.

Pointers are more efficient in handling arrays and data tables.

The use of pointer arrays to strings results in saving of data storage space in memory.

Pointers allow to change the calling functions arguments and to return multiple values from called function.

Pointers permit references to functions and thereby facilitating passing of functions as arguments to other functions.

The real power of C lies in the proper use of pointers. The misuse of pointers causes serious problems such as system crash.

11.3. Referencing operator (&)

Referencing operator is a unary operator. It acts on one operand at a time. It returns the address of operand. The operand must be a named region of storage (like int variable, array

variable, pointer variable etc.) for which a value may be assigned. The operand must not be a constant or an expression or a register variable. This operator is also called as address of

operator.

The & operator should be preceded with the operand in order to return the address.

Valid expressions:

&a

&c

//where a is the name of variable.

//where c is the name of an array.

&fact //where fact is the name of function.

Invalid expressions: &253 //constant cant be used as an operand.

&(a+b) //expression cant be used as an operand.

&r //register type cant be used as an operand.

Consider the declaration:

int a=20;

This declaration tells the C compiler to:

a) Reserve the required space in memory to hold the integer value.

b) Associate the name a with this memory location.

c) Store the value 20 at this location.

Suppose that the variable a occupies 2 bytes on 16-bit computer. This can be represented as follows:

From this memory map, it is clear that the data item 20 can be accessed with the help of name of variable as well as address of variable (or memory location or reference).

The conversion character %x is used to print address in hexa-decimal notation. The conversion character %u is used to print the address in decimal notation (especially, a positive

number to understand easily).

Program to print the address of variable in hexa decimal and decimal notations

#include

main()

int a=20;

printf(\n The address of a =%x,&a); //prints address in hexa decimal notation

printf(\n The address of a=%u,&a); // prints the address as a positive long integer

Dereferencing operator (*)

Dereferencing operator is a unary operator. It acts on one operand at a time. It returns the value stored at the address of operand. The operand must be an address, a pointer that holds

address or a pointer expression. This operator is also called as value at address operator or indirection operator.

The * operator should be preceded with the operand in order to return the value at address of operand.

Valid expressions: $*(\& $num) //where num is a variable

$*\& *\& $num

$**\& $num

Invalid expressions:

*2009

//constant value cant be used as an operand.

*num

//only addresses or pointers or pointer expressions can be used.

($*\& $)num //parentheses should not enclose two unary operators

Working with pointers:

In order to work with pointers, do the following:

1. Declare a pointer variable

2. Initialize it.

3. Access the original value through a pointer or perform any other operation on it.

Declaration of a pointer variable: Just like an ordinary variable, a pointer variable should be declared before it is used. This declaration has the following form:

In this syntax,

$ < $storage_class$ > $ is any one of the auto, static, extern or register.

$ < $data typte$ > $ is any one of int, float, char, double or void or data types such as signed int, long int etc,
The symbol * should be preceded with the name(s) of pointer(s).

<$ < $pointer_name$ > $ is any valid identifier. If there are more pointer_names, those should be separated with commas.
Ex:
int *iptr;
//pointer-to-int
float *fptr; //pointer-to-float
char *cptr; //pointer-to-char
The declaration int *iptr; does not mean that iptr is going to contain integer value. What it means is, iptr is a pointer variable that is going to hold the address of an integer value.
Hence, iptr is a pointer that points to integer value. In short, iptr is a pointer-to-int.
In the same way, the pointer fptr is going to contain the address of floating point value. Hence, fptr is a pointer that points to a floating point value. In short, fptr is a pointer-tofloat.
Similarly, the pointer cptr is going to contain the address of a character. Hence, cptr is a pointer that points to a character. In short, cptr is a pointer-to-char.
Initialization of a pointer variable: A pointer variable should be initialized with an address before it is used. The initialization of a pointer variable takes the following form:

Where Lvalue is any pointer variable and Rvalue is a variable preceded with an ampersand or a pointer of same type of LValue.

Ex:

int a=40;
int *iptr1,*iptr2;
//Declaring pointer variables: iptr1,iptr2
iptr1=&a;
//Initializing pointer variable: iptr1
iptr2=iptr1;
//Initializing pointer variable: iptr2
Whenever a pointer variable is initialized with the address of an ordinary variable or a pointer variable, we can say that the pointer variable points to that ordinary variable or pointer
variable. This can be represented as follows:

Accessing a pointer variable:


Once a pointer variable is initialized, it can be used to access the address as well as content of object to which it is pointed to. The following program demonstrates this:

Program to declare, initialize and access a pointer variable:

#include$ < $stdio.h$ > $

main()

int a=40;

int *iptr;

//Declaration: pointer-to-int

iptr=&a;

//Initialization: with the address of a

printf(\n The address of a=%u,&a);

printf(\n The address of a=%u,iptr); //accessed to print address of a

printf(\n The value of a=%d,a);

printf(\n The value of a=%d,*(&a));

printf(\n The value of a=%d,*iptr); //accessed to print the content of a

}
Operations on pointers:
Pointer arithmetic

The following arithmetic operations can be performed on pointers:


Addition of a number to a pointer.

Subtraction of a number from a pointer.

Subtraction of a pointer from another pointer.

The following arithmetic operations can not be performed on pointers:

Addition, multiplication, division and modulo division of two pointers.


Multiplication, division and modulo division of a pointer by a number.
Shifting operations.
Pointer increment and decrement:

Pointer
Expression
Ptr+n
Ptr-n
Ptr++
Ptr-++Ptr
--Ptr
*Ptr++
*Ptr--

Description
Ptr=Ptr+n*sizeof(data_type_of_pointer)
Use the original value of ptr and then n*sizeof(data_type_of_pointer) is
added to ptr after statement execution.
Ptr=Ptr-n*sizeof(data_type_of_pointer)
Use the original value of ptr and then n*sizeof(data_type_of_pointer) is
subtracted from ptr after statement execution.
Ptr=Ptr+ sizeof(data_type_of_pointer)
Use the original value of ptr and then ptr is incremented after statement
execution.
Ptr=Ptr- sizeof(data_type_of_pointer)
Use the original value of ptr and then ptr is decremented after statement
execution.
Ptr=Ptr+ sizeof(data_type_of_pointer)
Original Ptr is incremented before the execution of statement.
Ptr=Ptr- sizeof(data_type_of_pointer)
Original Ptr is decremented before the execution of statement.
*(Ptr++)
Retrieve the content of the location pointed to by pointer and then
increment ptr.
*(Ptr--)

*++Ptr
*--Ptr
(*Ptr)++
(*Ptr)--

Retrieve the content of the location pointed to by pointer and then


decrement ptr.
*(++ptr)
Increment pointer and then retrieve the content of the new location
pointed to by Ptr.
*(--Ptr)
Decrement pointer and then retrieve the content of the new location
pointer to by Ptr.
Retrieve the content of *Ptr of the location pointed to by Ptr, and then
Increment content of the location pointed to by Ptr. For pointer type
content, use pointer arithmetic of standard arithmetic.
Retrieve the content *Ptr of the location pointed to by Ptr, then decrement
the content of that location; Ptr is not changed.

Pointer comparisons:

Two pointers can be compared by using relational operators as well as logical operators. When these operators encountered, these expressions may return either true or false. program

to demonstrate pointer comparisons

#include$ < $stdio.h$ < $

main()

int a=40,b=34;

int *iptr1,*iptr2;

iptr1=&a;

iptr2=&b;

printf(\n Equal condition of two pointers=%d,(ip1==ip2));

printf(\n Not Equal condition of two pointers=%d,(ip1!=ip2));

printf(\n Greater than condition of two pointers=%d,(ip1>ip2));

printf(\n Lesser than condition of two pointers=%d,(ip1

printf(\n Greater than or equals condition of two pointers=%d,(ip1>=ip2));

printf(\n Lesser than or equals condition of two pointers=%d,(ip1<=ip2));

printf(\n Logical AND condition of two pointers=%d,( ip1>=ip2&&ip1==ip2));

printf(\n Logical OR condition of two pointers=%d,(ip1==ip2|| ip1

printf(\n Logical NOT condition of two pointers=%d,(!(ip1==ip2)));

* Comparing two pointers those point to different types of objects lead to error, although they have addresses as data items in them.

Various pointer declarations:

Declare a variable of type float?

float x;

Declare an array that holds 10 floating-point values?

float a[10];

Declare a function that takes a character as argument and returns a character as return value?

char fun(char);

Declare a pointer-to-float?

float *fptr;

Declare a function that returns a pointer-to-float?

float * fun(void);

Declare a pointer-to-function that takes a double argument and returns a double value?

double (*fun)(double);

Declare a pointer-to-10-integer element array?

int (*arrptr)[10];

Declare an array of integer pointers of size 10?

int *a[10];

Declare a pointer to char?

char *cptr;

Declare a pointer-to-pointer to a char?

char **cptr;

Declare a pointer-to-pointer-to-pointer to a char?

char ***cptr;

Declare a function that returns a pointer to the array of floats?

float (*fun())[10];

Declare an array of pointers to a function returning float?

float (*f[10])();

Problems with pointers:

1) Segmentation fault (or segfault):

This generally means that a program tried to access the memory it shouldnt have, invariably as a result of improper pointer use. The most likely causes could be inadvertent use of null
pointers or uninitialized, misaligned, or otherwise improperly allocated pointers, corruption of malloc area and mismatched function arguments, especially involving pointers; two possible
cases are scanf(%d,i) (without ampersand) and fprintf(invalid FILE* argument).
A segmentation fault occurs when an attempt is made to access memory whose address is well-formed, but to which access cant be granted. This might be due to either a
protection fault or an invalid page fault.

2) Un-initialized pointer:

This generally occurs when we declared a pointer, forgot to initialize it with an address and tried to access the content through pointer. E.g.,
int *ptr, val=300;
*ptr=val; /*Error*/
3) When we want to assign a value to a pointer variable, then that assignment leads to an error.
E.g.,
int *p, val=24;
p=val; /*Error*/
4) When we want to assign the address of un-initialized variable to a pointer, then that assignment also leads to an error.
E.g., int val,*ptr;
ptr=&val; /*Error*/
5) When we want to compare pointers those point to different objects, that comparison lead to an error
E.g., char name1[20],name2[20];
char *p1=name1;
char *p2=name2;
if(p1>p2).
/*Error*/

Pointer as an argument

Pointers can also be passed as arguments to a function as normal values are being passed. This method is also known as call by reference. By using these pointers, the calling
functions arguments can be changed from called function. Whenever we want to pass a pointer as an argument, these things should be carried out:
In function prototype, place an * after the type of argument to specify that we are passing a pointer as an argument.

In function call, place the argument- the address of operator followed by name of argument or the pointer that is declared earlier.

Develop the function definition based on the specified prototype.


Write a program to increment three values from called function and print them in calling function.
#include$ < $stdio.h$ > $
void increment(int *,int *,int *); //function prototype
main()
{
int a=20,b=30,c=40;
printf(\n Before increment a=%d\tb=%d\tc=%d,a,b,c);
increment(&a,&b,&c);

//function call

printf(\n After increment a=%d\tb=%d\tc=%d,a,b,c);


}
void increment(int *x,int *y,int *z) //function definition
{
++*x;
++*y;
++*z;
}
* Indirectly, a called function can return multiple values if pointers to these are passed as arguments.
Pointer as a return value

Pointers can also be returned to the calling function from called function as normal values. When we want to return a pointer to the calling function from called function, we should do
these:
In function prototype, place an * after the return type to indicate that the function returns a pointer.
In calling function, there should be a pointer variable that is declared to hold the pointer that is returned. However, both types should be the same to avoid ambiguities.

Develop the function definition as specified in function prototype. In function definition, the return statement, at end, should consist of an & before the return value or a pointer that is
declared earlier.
* Returning a pointer to local argument of called function to calling function gives you a warning.
A program that demonstrates pointer as return value

#include$ < $stdio.h$ > $


int * add(int,int); //function prototypefunction add() returns a pointer-to-int
main()
{
int a,b;
int *c;
printf(\n Enter the values of a and b: );
scanf(%d%d,&a,&b);
c=add(a,b);
printf(\n The result=%d,*c);
}
int * add(int x,int y) //function definition
{
int z;
z=x+y;
return (&z);
}
Output:
Enter the values of a and b: 10
12
The result=22
Pointer-to-function
We can also call a function using a pointer. To call a function using a pointer, do the following:
1.
First, declare a pointer to function that has the following form:
$ < $return type$ > $ (*$ < $name_of_ptr)(arg_type_1,arg_type_2,);
E.g., int (*addptr)(int,int);
The above declaration tells that addptr is a pointer to a function that takes two integer arguments and returns an integer value.
2.

Assign the name of the function to that pointer. The name of the function itself acts as an address of function.
E.g., addptr=add; // add should be the name of function

3. Call the function by using pointer in the same way as we call a function.
E.g., x=(*addptr)(10,20);
The above statement is used to call that function which is already assigned to pointer-to-function.
A program that demonstrates pointer-to-function
#include$ < $stdio.h$ > $
int add(int,int); //function prototype No change, give prototype normally.
main()
{
int a,b,c;
int (*addptr)(int,int); //step-1: pointer-to-function declaration
printf(\n Enter the values of a and b: );
scanf(%d%d,&a,&b);
addptr=add; //step-2: Assign name of function to the pointer
c=(*addptr)(a,b); //step-3 call the function using pointer
printf(\n The result=%d,c);
}
int add(int x,int y) //function definition- No change, give definition normally
{
int z;
z=x+y;
return z;
}
Output:
Enter the values of a and b: 10
12
The result=22
A pointer-to-function can be passed to another function as an argument. This allows one function to be transferred to another function. Let us refer to the first function as the guest
function and the second function as host function. Thus the guest function is passed to the host function, where it can be accessed. When we want to pass a function as an argument
to another function, do the following:
1)
2)
3)
4)

While calling the host function, place the name of the guest function as an argument. The name itself serves as a pointer to guest function.
Give the definition of guest function as usual.
In the definition of host function, place a pointer to guest function as an argument.
In the definition of host function, call guest function for further process.

Program that demonstrates function as an argument to another function


#include$ < $stdio.h$ > $
int add(int,int); //guest function prototype
void swap(int(*)(int,int));//host function prototype
int a,b;
main()
{
printf("\n Enter any two numbers:");
scanf("%d%d",&a,&b);
swap(add);

//step-1

printf("\n After swap a=%d\tb=%d",a,b);


}
int add(int x,int y) //step-2
{
return x+y;
}
void swap(int (*addptr)(int,int)) //step-3
{
a=(*addptr)(a,b); //step-4
b=(*addptr)(a,-b); //step-4
a=(*addptr)(a,-b); //step-4
}
Output:
Enter any two numbers: 32
45
After swap a=45

b=32

Casting pointers
A pointer always has a type associated with it. As we can convert a variable of one type to another, we can also convert one type of pointer to another type of pointer. This process of
conversion is called as casting pointers. Unlike variables, we cant assign one type of pointer variable with another type of pointer variable, although both of them have memory
addresses as their values. This is known as incompatibility of pointers.
We cant use the assignment operator with the pointers of different types. We can, however, make explicit assignment between two incompatible pointer types by using cast
operator, as we do with fundamental types. The cast operator can be used as follows:
$ < $ptr1$ > $=($ < $data type$ > $ *)$ < $ptr2$ > $;

In this syntax, ptr2 is a pointer variable of a data type that is going to be converted to the type of ptr1. Usually, the is same as the type of $ < $ptr1$ >
Program that demonstrates casting from one type to another
#include$ < $stdio.h$ > $
main()
{
int a=65;
int *iptr=&a;
char *cptr;
cptr=(char *)iptr;
printf("%c",*cptr);
}
Output:
A

Dynamic memory allocation

Though arrays can be used for data storage, they are of fixed size. The programmer must know the size of the array while writing the program. In most situations, it is not possible to
know the size of the memory required until run time. At execution time, a program can request more memory from a free memory pool (heap). Dynamic memory allocation refers to the
allocation of such memory during program execution. The only way to access this dynamically allocated memory is through pointers.
What are the differences between dynamic memory allocation and static memory allocation?

Static memory allocation


It is the process of allocating memory at

Dynamic memory allocation


It is the process of allocating memory

compile time.
Fixed number of bytes will be allocated.
The memory is allocated in memory
stack.

during execution of program.


Memory is allocated as and when it is
needed.
The memory is allocated from free
memory pool (heap).

* The limit for dynamic memory allocation can be as large as the amount of available physical memory in the computer or the amount of available virtual memory in a virtual memory
system.

C supports many built-in standard library functions for efficient dynamic memory
files stdlib.h, alloc.h and malloc.h. These functions are: malloc(), calloc(), realloc() and free().

allocation

de-allocation.

Their

prototypes

are

declared

in

the

header

1) malloc() allocates a block of memory


The function malloc() has the following prototype:
void *malloc(size_t size);
The function malloc() allocates a block of size bytes from the free memory pool (heap). It allows a program to allocate an exact amount of memory explicitly, as and when needed.
Argument: The parameter passed to malloc() is of the type size_t. This type is declared in the header file stddef.h. size_t is equivalent to the unsigned int data type. Thus, in compilers
where an int is 16 bits in size, malloc() can allocate a maximum of 64KB at a time, since the maximum value of an unsigned int is 65535.

Return value:
On success, i.e., if free memory is available, malloc() returns a pointer to the newly allocated memory. Usually, it is generic pointer. Hence, it should be typecast to
appropriate data type before using it to access the memory allocate.
On failure, i.e., if enough free memory does not exist for block, malloc() returns NULL. The constant NULL is defined in stdio.h to have a value zero. Hence, it is safe to
check the return value.

Ex: 1) malloc(30); allocates 30 bytes of memory and returns the address of byte0.
2) malloc(sizeof(float)); allocates 4 bytes of memory and returns the address of byte0.
What do malloc(-20) and malloc(0) return?
The parameter to malloc() function should be an unsigned integer. If we pass any negative value as an argument, then NULL is returned. So, malloc(-20) returns NULL.
Though the value 0 is not a negative integer, malloc(0) does not return pointer to 0 bytes or NULL pointer. Instead, it also returns the constant NULL.
2) calloc() allocates multiple blocks of memory
The function malloc() has the following prototype:
void *calloc(size_t nitems,size_t size);
calloc() provides access to the C memory heap, which is available for dynamic allocation of variable-sized blocks of memory.
Arguments: Unlike malloc(), the function calloc() accepts two arguments: nitems and size. The parameter nitems specifies the number of items to allocate and size specifies the size of
each item.
Return value:
On success, i.e., if free memory is available, calloc() returns a pointer to the newly allocated memory. Usually, it is generic pointer. Hence, it should be typecast to appropriate data type before
using it to access the memory allocated.
On failure, i.e., if enough free memory does not exist for block, calloc() returns NULL. The constant NULL is defined in stdio.h to have a value zero. Hence, it is safe to verify the return value
before using it.
Ex: 1) calloc(3,5); allocates 15 bytes of memory and returns the address of byte0.
2) malloc(6,sizeof(float)); allocates 24 bytes of memory and returns the address of byte0.

3) realloc() grows or shrinks allocated memory


The function malloc() has the following prototype:
void *realloc(void *block,size_t size);

The function realloc() adjusts the amount of memory allocated to the block to size, copying the contents to a new location if necessary.
Arguments: block is the pointer to the memory block that is previously obtained by calling malloc(), calloc() or realloc(). If blockis NULL pointer, realloc() works just like malloc().
Size is the new size for allocated block.
Return value:
On success, this function returns the address of the reallocated block, which might be different from the address of the original block.

On failure, i.e., if the block cant be reallocated or if the size passed is 0, the function returns NULL.

The function realloc() is more useful when the maximum size of allocated block can not be decided in advance.
Ex: int *a;
a=(int *) malloc(30); //first 30 bytes of memory is allocated.
Why does not sizeof operator tell us the size of block of memory pointed by a pointer?
The sizeof operator does not know the at malloc() has been used to allocate pointer; sizeof tells us the size of the pointer itself. There is no portable way to find out the size of a block
allocated by malloc().
a=(int *) realloc(a,15); //later the allocated memory is shrink to 15 bytes.

4) free() de-allocates memory


The function free() has the following prototype:
void free(void *block);
The function free() de-allocates a memory block pointed by block.
Argument: block is the pointer that is points to allocated memory by malloc(), calloc() or realloc(). Passing an uninitialized pointer, or a pointer to a variable not allocated by malloc(),
calloc() or realloc() could be dangerous and disastrous.
Ex: int *a;
a=(int *) malloc(30); //first 30 bytes of memory is allocated.
free(a); //de-allocates 30 bytes of memory.
How does free() know how many bytes to free?
The malloc() / free() implementation remembers the size of each block allocated and returned. So, it is not necessary to remind it of the size when freeing.
Pointers and One-Dimensional numeric arrays
An array is homogeneous collection of elements stored in contiguous memory locations referred by common name. The array name itself is the base address, i.e., the address of first
element in array. As we know that the pointer is an address, the array name itself is a pointer.

1.
2.
3.

Accessing array elements through a pointer


Usually, each element in an array is accessed through an index that starts from 0 and ends with n-1 where n is the size of array. e.g., a[0] is the first element, a[1] is second element and
so on
Similarly, by using a pointer variable, all the elements are accessed as follows:
First declare a pointer variable. The type of pointer variable should be same as the type of array.
Initialize the pointer variable with the base address of array.
Access each element by placing an * before incremented pointer or before the expression of the form (ptr+i) where ptr is the pointer variable and i is the index value.
The following program demonstrates this:
Write a program to add elements of array using a pointer
#include$ < $stdio.h$ > $
void display(int *,int);
void sum(int *,int);
main()
{
int a[10],n,i,*ptr; //step-1: Declaration of a pointer variable
printf(\n Enter the array size:);
scanf(%d,&n);
printf(\nEnter the array elements:);
for(i=0;i
scanf(%d,&a[i]);
ptr=&a[0]; //step-2: Initalization of pointer variable
display(a,n); //the name of the array itself is the base address
sum(ptr,n);
}
void display(int a[ ],int n)
{
int i;
printf(\n The array elements are:);
for(i=0;i
printf(%d\t,a[i]);
}
void sum(int *ptr,int n)
{

int i,total;
total=0;
//step-3: Accessing array elements through pointer
for(i=0;i
total=total+*ptr++; //or total=total+*(ptr+i);
printf(\n The sum of array elements=%d,total);
}
Output:
Enter the array size:5
Enter the array elements: 2 4 6 3 1
The array elements are: 2 4

The sum of array elements=16


Note:
a[i] is equivalent to i[a] or *(a+i) or *(i+a)

Dynamically allocated 1-D array


When we declare an array, we declare it as an array of fixed size. It cant be grown or shrink as and when needed. To overcome this problem, dynamically allocated array is introduced.
To work with dynamically allocated array, do the following:
1.
Declare a pointer variable.
2.

Allocate memory to that pointer variable.

3.

Initialize and access array elements through pointer variable.

4.

De-allocate the pointer variable.

The following program demonstrates this concept:


Write a program to sort elements of array using pointers.
#include$ < $stdio.h$ > $
void display(int *,int);
void sort(int *,int);
main()
{
int *a,n,i; //step-1: Declaration of a pointer variable
printf(\n Enter the array size:);
scanf(%d,&n);
a=(int *) malloc(n*sizeof(int)); //step2: Allocate memory
printf(\nEnter the array elements:);
for(i=0;i
scanf(%d,a+i);
display(a,n);
sort(a,n);
free(a); //step-4: de-allocating memory
}
void display(int a[ ],int n)
{
int i;
printf(\n The array elements are:);
for(i=0;i
printf(%d\t,a[i]); //step-3: accessing elements
}
void sort(int *ptr,int n)
{
int i,j,temp;
for(i=0;i
{
for(j=i+1;j
{
if(*(ptr+i)>*(ptr+j))

//step-3: accessing elements

{
temp=*(ptr+i);
*(ptr+i)=*(ptr+j);
*(ptr+j)=temp;
}
}
}
printf(\n After sorting:);
display(ptr,n);
}

Note:
a[i] is equivalent to i[a] or *(a+i) or *(i+a)
Can we use the content of allocated memory after freeing it?
Some early documentation for malloc() stated that the contents of freed memory were left undisturbed. So, few programmers would use the contents of freed memory deliberately.
Function returning 1-D array
By using pointers, a function can return more than one value at a time. As array contains more than one element and array name is the base address, we can return the base address.
This gives us a view that a function can return more than one value at a time. The following program demonstrates this concept:
Write a program to demonstrate a function that returns a sorted array.
#include$ < $stdio.h$ > $
int * sort(int a[ ],int); //function prototype
main()
{
int *p;
int a[10],n,i;
printf("\n Enter the array size:");
scanf("%d",&n);
printf("\n Enter the array elements:");
for(i=0;i
scanf("%d",&a[i]);
printf("\n Before sorting:");
for(i=0;i
printf("%d\t",a[i]);
p=sort(a,n); //function call- p holds the base address of returned array
printf("\n After sorting:");
for(i=0;i
printf("%d\t",*p++);
}
int *sort(int a[ ],int n)
{
int i,j,temp;
for(i=0;i
{
for(j=i+1;j
{
if(a[i]>a[j])
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
return a; //sends the base address of sorted array
}
Output:
Enter the array size: 5
Enter the array elements:35
3
46
43
1
Before sorting: 35

46

43

After sorting: 1

35

43

Pointers and Two-Dimensional numeric arrays


The two-dimensional array is an array with two subscripts. As same with one-dimensional numeric array, the name of two-dimensional array is also a base address. i.e., it is the address
of element that is present in first row and first column (address of a[0][0]).
Pointer-to-2-D array
The way we can have a pointer to an integer, or a pointer to a float, can we also have a pointer to an array? The answer is YES. A two-dimensional array can be accessed through a
pointer as follows:
1.
First, declare a pointer to array. This declaration of pointer-to- 2-D array is little clumsy. It has the following form:
$ < $data type$ > $ (*$ < $ptr_name$ > $)[size];
Ex: int (*q)[4];
This declaration gives a meaning that q is a pointer-to-2-D array of 4 columns.

2.

Once a pointer is declared, it should be initialized with the name of 2-D array that
declared and initialized earlier.
e.g., ptr=a; where a is two-dimensional array.
3.
Now, each element gets accessed with the help of the following expression:
*(*(ptr+i)+j) where i is the index of row and j is the index of column.

Write a program to access a 2-D array using pointer and print it in matrix form
#include$ < $stdio.h$ > $
main()
{
int a[10][10],m,n,i,j;
int (*ptr)[10]; //pointer-to-array
printf(\n Enter the matrix row and column values:);
scanf(%d%d,&m,&n);
printf(\n Enter matrix elements:);
for(i=0;i
for(j=0;j
scanf(%d,&a[i][j]);
ptr=a;
printf(\n The matrix elements:\n);
for(i=0;i
{
for(j=0;j
{
printf(%d\t,*(*(ptr+i)+j));
printf(\n);
}
}
}
Output:
Enter matrix row and column values: 2 2
Enter matrix elements: 23 45 65 232
The matrix elements:
23

45
65

232

Dynamically allocated 2-D array


When we declare an array, we declare it as an array of fixed size. It cant be grown or shrink as and when needed. To overcome this problem, dynamically allocated array is introduced.
To work with dynamically allocated array, do the following:
1.
Declare a pointer variable.
2.

Allocate memory to that pointer variable.

3.

Initialize and access array elements through pointer variable.

4.

De-allocate the pointer variable.

The following program demonstrates this concept:


/*A program to multiply two matrices using pointers*/
#include$ < $stdio.h$ > $
void display(int **,int,int);
void multiply(int **,int **,int,int,int,int);
main()
{
int **a,**b,m,n,p,q,i,j; //step-1
printf("\n Enter the first matrix order:");
scanf("%d%d",&m,&n);
printf(\n Enter second matrix order:);
scanf(%d%d,&p,&q);
if(n!=p)
printf(\n Sorry, matrix multiplication is not possible);
else
{
a=(int **)malloc(m*sizeof(int));
for(i=0;i
a[i]=(int *)malloc(n*sizeof(int));
printf("\n Enter first matrix elements");
for(i=0;i
for(j=0;j

scanf("%d",&a[i][j]);
printf(\n First matrix\n);
display(a,m,n);
b=(int **)malloc(p*sizeof(int));
for(i=0;i
a[i]=(int *)malloc(q*sizeof(int));
printf("\n Enter second matrix elements");
for(i=0;i
for(j=0;j
scanf("%d",&b[i][j]);
printf(\n Second matrix\n);
display(b,p,q);
multiply(a,b,m,n,p,q);
free(a);
free(b);
}
}
void display(int **a,int m,int n)
{
nt i,j;
for(i=0;i
{
for(j=0;j
printf("%d\t",a[i][j]);
printf(\n);
}
}
void multiply(int **a,int **b,int m,int n,int p,int q)
{
int **c,i,j;
c=(int **)malloc(m*sizeof(int));
for(i=0;i
c[i]=(int *)malloc(q*sizeof(int));
for(i=0;i
{
for(j=0;j
{
c[i][j]=0;
for(k=0;k
c[i][j]=c[i][j]+a[i][k]*b[k][j];
}
printf(\n The resultant matrix:\n);
display(c,m,q);
free(c);
}
(Click next to read rest of the article)

Array of pointers
There is an array of ints or an array of floats. Similarly, there can also be an array of pointers. Since, a pointer is an address; an array of pointers is nothing but a collection of addresses.
The addresses present in the array of pointers can be addresses of isolated variables or addresses of array elements or any other addresses. All rules that apply to an ordinary array
apply to the array of pointers as well. The following program demonstrates the concept of array of pointers:
Write a program to demonstrate array of pointers.
#include$ < $stdio.h$ > $
main()
{
int *a[4]; //declaration of array of pointers
int i=32,j=45,k=2,l=35,m;
a[0]=&i;
a[1]=&j;
a[2]=&k;
a[3]=&l;
for(m=0;m<3 data-blogger-escaped-m="m" data-blogger-escaped-o:p="o:p">

printf(%d\t,*(a[m])); //accessing the content in each element that is a pointer


}
Output: 32

45

35

Write a program to print transpose a matrix using array of pointers.


#include$ < $stdio.h$ > $
main()
{
int *a[10];
int m,n,i,j;
printf("\n Enter matrix order");
scanf("%d%d",&m,&n);
for(i=0;i
a[i]=(int *)malloc(n*sizeof(int));
printf("\n Enter matrix elements:");
for(i=0;i
for(j=0;j
scanf("%d",&a[i][j]);
printf("\n The original matrix\n");
for(i=0;i
{
for(j=0;j
printf("%d\t",a[j][i]);
printf("\n");
}
printf("\n The transpose of matrix\n");
for(i=0;i
{
for(j=0;j
printf("%d\t",a[j][i]);
printf("\n");
}
}
Output:
Enter matrix order: 2 3
Enter matrix elements: 1 2 3 4 5 6
The original matrix
1

The transpose of matrix


1

6
Write a program to print transpose of a matrix using pointer-to-array
#include$ < $stdio.h$ > $
main()
{
int a[10][10],m,n,i,j;
int (*ptr)[10]; //pointer-to-array
printf(\n Enter the matrix row and column values:);
scanf(%d%d,&m,&n);
printf(\n Enter matrix elements:);
for(i=0;i
for(j=0;j
scanf(%d,&a[i][j]);
ptr=a;
printf(\n The matrix elements:\n);
for(i=0;i
{

for(j=0;j
{
printf(%d\t,*(*(ptr+i)+j));
printf(\n);
}

}
printf(\n The transpose of matrix:\n);
for(i=0;i
{

for(j=0;j
{
printf(%d\t,*(*(ptr+j)+i));
printf(\n);
}

}
}
Output:
Enter matrix row and column values: 2 2
Enter matrix elements: 23 45 65 232
The matrix elements:
24

45

65

232
The transpose of matrix:
24

65
45

232

Compare array of pointers to pointer-to-array?


1) A pointer to an array is a variable that contains the address of (points to) a multi-dimension variable that could contain anything (multiple strings or multiple longs etc.).
An array of pointers is a single-dimensional variable that holds multiple addresses (pointers) each of which could point to anything (other variables, objects etc.).
2) The number in subscript of pointer-to-array denotes the number of columns.
The number in subscript of array of pointers denotes the number of rows.
Pointers and Strings
As a group of integers is stored in an integer array, a group of characters will be stored in a character array. This character array is called as a string. Usually, a string constant is a onedimensional array of characters terminated by a null character (\0).
Accessing a string by using a pointer
Because a string is one-dimensional array of characters and the array name is the base address, the name of the character array also becomes the base address. In order to access
string with the help of pointer, do the following:
1.
First declare a pointer of type char.
e.g., char *ptr; //A character pointer
2.
Initialize the pointer with the name of character array that was declared and initialized earlier.
e.g., char s[]=Ravi Chandra;
ptr=s; //holds the base address of character array s
3.
Access each character of string with the help of pointer by incrementing once till the \0 character is encountered.
e.g., while(*ptr!=\0)
{
printf(%c,*ptr);
ptr++;
}
Write a program to read a string and print a string along with its length
#include$ < $stdio.h$ > $
int stringlength(char *);
main()
{
char s[ ]=Ravi Chandra;
char *ptr;
int len;
cptr=s;
len=stringlength(s);
printf(\n The length of string=%d,len);
}
int stringlength(char *s)
{
int count=0;
printf(\n Given string is=);
while(*s!=\0)
{
printf(%c,*s);
count++;
s++;

}
return count;
}
Output:
Given string is= Ravi Chandra
The length of string=12
Write a program to count number of alphabets, digits, spaces and special characters in a line of text
#include$ < $stdio.h$ > $
main()
{
char line[100];
char *ptr;
int nalpha,ndigit,nspace,nspecial;
printf(\n Enter a line of text:);
scanf(%[ ^\n],line);
ptr=line;
nalpha=nspace=ndigit=nspecial=0;
while(*ptr!=\0)
{
if(toupper(*ptr)>=A && toupper(*ptr)<=Z)
nalpha++;
else if(*ptr>=0&&*ptr<=z)
ndigit++;
else if(*ptr= = || *ptr= =\t)
nspace++;
else
nspecial++;
}
printf(\n No.of alphabets=%d,nalpha);
printf(\n No.of digits=%d,ndigits);
printf(\n No.of spaces=%d,nspace);
printf(\n No.of special characters=%d,nspecial);
}
Output:
Enter a line of text: Master says, B.Tech 1st year students are brilliant
No.of alphabets=41
No.of digits=1
No.of spaces=5
No.of special symbols=4
Pointer to a string
Suppose we wish to store the string Hello friend. We may either store it in a character array or we may ask the C compiler to store it some where in memory and assign the address of
that string in a char pointer. This is shown below:
char message[ ]=Hello friend;
char *p=Hello friend;
However, there are differences between these two:
1.
Ex:

The size of character array will be more than the size of the character pointer.
#include$ < $stdio.h$ > $
main()
{
char message[]=Hello friend;
char *p=Hello friend;
printf(\n Size of character array=%d,sizeof(message));
printf(\n Size of character pointer=%d,sizeof(p));
}

Output (on 32-bit machine):


Size of character array=13
Size of character pointer=4
2.
Ex:

A char pointer can be assigned to another char pointer; but a character array cant be assigned to another character array.
#include$ < $stdio.h$ > $
main()
{
char message[ ]=Hello friend;
char mesg2[20];
char *p=Hello friend;

char *q;
mesg2=message; //A blunder
q=p;

//works

}
3.
Once a string has been defined using character array, it cant be initialized to another set of characters. Unlike character array, such an operation is perfectly valid
with char pointer.
Ex:

#include$ < $stdio.h$ > $


main()
{
char message[]=Bye Forever;
char *p=Bye forever;
message=welcome friend; // A blunder
p=Welcome friend;
}

Array of pointers to strings


As an array of integer pointers is used to represent a two-dimensional array of integers, array of character pointers is used to hold multiple strings. To deal with multiple strings with the
help of array of character pointers, do the following:
1.

First, declare an array of character pointers.

e.g., char *a[10];


This declaration is used to define a 10-element array of pointers. Thus, a[0] points to first string, a[1] points to second string and so on.
2.

It is not necessary to include a maximum string size within declaration. However, it is necessary to allocate maximum string size as follows:

for(i=0;i
a[i]=(char *) malloc(15*sizeof(char)); //15 is each strings maximum length
3.

After memory is allocated, the array of character pointers can be initialized and accessed as normal arrays.

The following program demonstrates this concept:


Why cant I get strcat() to work? I tried
char *s1=Hello;
char *s2=World;
strcat(s1,s2);
printf(%s,s1);
The main problem here is that the space for the concatenated result is not properly allocated. C compilers allocate memory only for specified objects explicitly mentioned in the source
code. The programmer must arrange for sufficient space for the results of run-time operations, such as string concatenation, typically by declaring arrays or by calling malloc().
The strcat() function performs no allocation. Since, there is no space for concatenated result in first string (or destination string), the strcat() function returns run-time error.
Write a program to sort names using array of character pointers.
#include$ < $stdio.h$ > $
main()
{
int n,i,j;
char *names[10],*temp;
printf(\n Enter how many strings:);
scanf(%d,&n);
for(i=0;i
names[i]=(char *) malloc(15*sizeof(char));
printf(\n Enter %d names:,n);
for(i=0;i
scanf(%s,names[i]);
for(i=0;i
{

for(j=i+1;j
{

if(strcmp(names[i],names[j])>0)
{
temp=names[i];
names[i]=names[j];
names[j]=temp;
}

}
}

printf(\n Names in alphabetical order:);


for(i=0;i
printf(%s\t,names[i]);
}
Output:
Enter how many strings: 5
Enter 5 names:
Master
Minister
Servant
King
Queen
Names in alphabetical order: King

Master

Minister

Queen

Servant

Compare arrays and pointers?


n 1) An Arrray is a homogeneous collection of elements stored in contiguous memory locations referred by a common name.A pointer is a special type of variable that holds address as a data item in
it. The address is may be of a variable, or of a constant, or of an array, or of a function, or of another pointer.
2) An array can hold a collection of pointers.
A pointer can hold the base address of an array that is collection of elements.
3) An array cant be assigned to another array (even of same type) directly.
A pointer can be assigned to another pointer (of same type only) directly.
4) A pointer can be incremented.
An array name (though it is an address of first element) can not be incremented.
5) The size of array is fixed. It can never be changed.
memory allotted to a pointer can be reallocated.

Pointers and const

1)

As we know that const is the keyword that is used to define a symbolic constant that never be changed throughout the program. E.g., the following is the constant definition:
const float PI=3.1412;
This definition defines a constant PI and this value never be changed through out the program.
Pointer to constant
When we want to deal with a pointer to constant, do the following:
Declare a pointer to constant that has the following form:

const $ < $data type$ > $ * $ < $ptr_name$ > $;

2)

3)

E.g., const int *p;


The above statement declares p as a pointer to constant integer.
Once a pointer is declared, initialize it with the address of a const value or const array.
E.g., const int a=23;
p=a; //initialization of pointer with base address of array of constants
Access the const value or const array with the help of pointer.
It is important to note that the value that is being pointed can never be changed. But the pointer that points to constant can be changed. In other words, it can be incremented or
decremented.
E.g., The following program demonstrates this concept:
#include$ < $stdio.h$ > $
main()
{
const int *ptr1,*ptr2;
const int i=20;
const int a[ ]={10,20,40,23};
ptr1=&i;
ptr2=a;
printf(%d,*ptr1); //prints the value of i
i=30;

//a blundertrying to change the content of const

printf(%d,*ptr1);
ptr2++; //valida pointer to const can be changed
printf(%d,*ptr2); // prints the value of a[1]
}
Note: These types of pointers are very useful in char pointers, when pointers are to be passed to a function for printing. Suppose, we are writing a function that is aimed to print a
character string, it is good practice to code that function as follows:
void printstring(const char *str)
{
printf(%s,str);
}
The above function accepts a pointer of type const char *(pointer to constant character). The string that is being pointed can never be changed. This is safety measure, since it prevents
the accidental modification of the string that is being passed to called function.

nter-to-constant means that the value is not changed through that pointer, not which is unchanged through any
pointer.

Constant pointer
When we want to deal with a constant pointer, do the following:
1) Declare a constant pointer that has the following form:
$ < $data type$ > $ * const $ < $ptr_name$ > $=$ < $address$ > $;
E.g.,

int a=20;
int * const p=&a;
The above statement declares p as a constant pointer that holds the address of a.
2) Access the constant pointer to print the original content of variable or array whose address is stored.
E.g., printf(%d,*p); //prints the value of a
It is important to note that the value that is being pointed can be changed. In the above example, the value of a can be changed. But the value of constant pointer can never be changed.
i.e., in the above example, p++ or ++p is invalid.
Note: const int * const p=&a;
The above declaration disallows the modification of both p and a. i.e., both pointee and pointer.
What is the difference between const char *p and char* const q?
1)

p is a pointer-to-constant char.
P will be changed. But *p will never be changed.

2)

q is a constant pointer.
q will never be changed. But *q will be changed.