Page 1
Address Arithmetic
If p is a pointer to som e elem ent o f an array, then p ++ increm ents p to point to the next element,
and p +=i increm ents it to point i elem ents beyond w here it currently does. These and sim ilar
constructions are the sim ples form s o f pointer or address arithm etic. All types o f arithm etic
operations are not possible w ith pointers. The valid operations that can be perform ed using
pointers are
(i) A ddition o f an integer to a pointer and increm ent operation.
(ii) Subtraction o f an integer from a ponter and decrem ent operation.
(iii) Subtraction o f a pointer from another pointer o f sam e type.
The arithm etic operations that cannot be perform ed on pointers are as follow s
(i) A ddition, m ultiplication and division o f tw o pointers.
(ii) M ultiplication betw een pointer and any number.
(iii) D ivision o f a pointer by any number.
(iv) A ddition o f float or double values to pointers.
The expression p+1 yields the correct m achine address for the next variable o f that type. O ther
valid pointer expressions:
p+i, ++p, p+=I, p-q
w here p-q represents the N o o f array elem ents betw een p and q.
Since a pointer is ju st a m em address, w e can add to it to traverse an array.
p+1 returns a ptr to the next array element.
Precedence level o f * operator and increm ent/decrem ent operators is sam e and their associativity
is from right to left. In reality, p+1 doesn’t add 1 to the m em ory address, it adds the size o f the
array element.
Suppose p is an integer pointer and x is an integer variable. N ow the m ain problem is to identify
how the follow ing pointer expressions given below are interpreted.
(i) x = *p++ is same as tw o expressions x = *p follow ed by p = p + 1.
(ii) x = (*p)++ is same as tw o expressions x = *p follow ed by *p = *p + 1.
(iii) x=*++p is same as tw o expressions p=p+1 follow ed by x=*p.
(iv) x=++*p is sam e as tw o expressions *p=*p+1 follow ed by x=*p
C is consistent and regular in its approach to address arithm etic; its integration o f pointers, arrays,
and address arithm etic is one o f the strengths o f the language. Let us illustrate by w riting a
rudim entary storage allocator. There are tw o routines. The first, a l l o c (n ), returns a pointer to n
consecutive character positions, w hich can be used by the caller o f a l l o c for storing characters.
The second, a f r e e (p ), releases the storage thus acquired so it can be reused later. The routines
are ''rudim entary'' because the calls to a f r e e m ust be m ade in the opposite order to the calls m ade
Page 2
Address Arithmetic
If p is a pointer to som e elem ent o f an array, then p ++ increm ents p to point to the next element,
and p +=i increm ents it to point i elem ents beyond w here it currently does. These and sim ilar
constructions are the sim ples form s o f pointer or address arithm etic. All types o f arithm etic
operations are not possible w ith pointers. The valid operations that can be perform ed using
pointers are
(i) A ddition o f an integer to a pointer and increm ent operation.
(ii) Subtraction o f an integer from a ponter and decrem ent operation.
(iii) Subtraction o f a pointer from another pointer o f sam e type.
The arithm etic operations that cannot be perform ed on pointers are as follow s
(i) A ddition, m ultiplication and division o f tw o pointers.
(ii) M ultiplication betw een pointer and any number.
(iii) D ivision o f a pointer by any number.
(iv) A ddition o f float or double values to pointers.
The expression p+1 yields the correct m achine address for the next variable o f that type. O ther
valid pointer expressions:
p+i, ++p, p+=I, p-q
w here p-q represents the N o o f array elem ents betw een p and q.
Since a pointer is ju st a m em address, w e can add to it to traverse an array.
p+1 returns a ptr to the next array element.
Precedence level o f * operator and increm ent/decrem ent operators is sam e and their associativity
is from right to left. In reality, p+1 doesn’t add 1 to the m em ory address, it adds the size o f the
array element.
Suppose p is an integer pointer and x is an integer variable. N ow the m ain problem is to identify
how the follow ing pointer expressions given below are interpreted.
(i) x = *p++ is same as tw o expressions x = *p follow ed by p = p + 1.
(ii) x = (*p)++ is same as tw o expressions x = *p follow ed by *p = *p + 1.
(iii) x=*++p is same as tw o expressions p=p+1 follow ed by x=*p.
(iv) x=++*p is sam e as tw o expressions *p=*p+1 follow ed by x=*p
C is consistent and regular in its approach to address arithm etic; its integration o f pointers, arrays,
and address arithm etic is one o f the strengths o f the language. Let us illustrate by w riting a
rudim entary storage allocator. There are tw o routines. The first, a l l o c (n ), returns a pointer to n
consecutive character positions, w hich can be used by the caller o f a l l o c for storing characters.
The second, a f r e e (p ), releases the storage thus acquired so it can be reused later. The routines
are ''rudim entary'' because the calls to a f r e e m ust be m ade in the opposite order to the calls m ade
on a l lo c . That is, the storage managed by a llo c and afree is a stack, or last-in, first-out. The
standard library provides analogous functions called m a llo c and free that have no such
restrictions.
The easiest implementation is to have a llo c hand out pieces of a large character array that we will
call a l l o c b u f . This array is private to a llo c and a fre e . Since they deal in pointers, not array
indices, no other routine need know the name of the array, which can be declared s t a t i c in the
source file containing a llo c and afre e , and thus be invisible outside it. In practical
implementations, the array may well not even have a name; it might instead be obtained by
calling m a llo c or by asking the operating system for a pointer to some unnamed block of storage.
The other information needed is how much of allocbuf has been used. We use a pointer, called
a l l o c p , that points to the next free element. When a llo c is asked for n characters, it checks to
see if there is enough room left in a llocbuf . If so, a llo c returns the current value of a l l o c p (i.e.,
the beginning of the free block), then increments it by n to point to the next free area. If there is
no room, a llo c returns zero. afree(p) merely sets a l lo c p to pif p is inside allocbuf .
#define ALLOCSIZE 10000 s t a t i c
char allocbuf[A L L O C S IZ E ];
s t a t i c c h a r * a llo c p = allocbuf;
c h a r * a llo c (in t n)
{
i f (allocbuf + ALLOCSIZE - a llo c p > = n) {
allocp += n;
return allocp - n;
} else
return 0;
}
v o id afree(char *p)
{
i f (p >= allocbuf&& p <allocbuf + ALLOCSIZE) allocp = p;
}
In general a pointer can be initialized just as any other variable can, though normally the only
meaningful values are zero or an expression involving the address of previously defined data of
appropriate type. The declaration
s t a t i c c h a r *allocp = allocbuf;
defines allocp to be a character pointer and initializes it to point to the beginning of allocbuf ,
which is the next free position when the program starts. This could also have been written
s t a t i c char *allocp = &allocbuf[0];
since the array name is the address of the zeroth element. The test
Page 3
Address Arithmetic
If p is a pointer to som e elem ent o f an array, then p ++ increm ents p to point to the next element,
and p +=i increm ents it to point i elem ents beyond w here it currently does. These and sim ilar
constructions are the sim ples form s o f pointer or address arithm etic. All types o f arithm etic
operations are not possible w ith pointers. The valid operations that can be perform ed using
pointers are
(i) A ddition o f an integer to a pointer and increm ent operation.
(ii) Subtraction o f an integer from a ponter and decrem ent operation.
(iii) Subtraction o f a pointer from another pointer o f sam e type.
The arithm etic operations that cannot be perform ed on pointers are as follow s
(i) A ddition, m ultiplication and division o f tw o pointers.
(ii) M ultiplication betw een pointer and any number.
(iii) D ivision o f a pointer by any number.
(iv) A ddition o f float or double values to pointers.
The expression p+1 yields the correct m achine address for the next variable o f that type. O ther
valid pointer expressions:
p+i, ++p, p+=I, p-q
w here p-q represents the N o o f array elem ents betw een p and q.
Since a pointer is ju st a m em address, w e can add to it to traverse an array.
p+1 returns a ptr to the next array element.
Precedence level o f * operator and increm ent/decrem ent operators is sam e and their associativity
is from right to left. In reality, p+1 doesn’t add 1 to the m em ory address, it adds the size o f the
array element.
Suppose p is an integer pointer and x is an integer variable. N ow the m ain problem is to identify
how the follow ing pointer expressions given below are interpreted.
(i) x = *p++ is same as tw o expressions x = *p follow ed by p = p + 1.
(ii) x = (*p)++ is same as tw o expressions x = *p follow ed by *p = *p + 1.
(iii) x=*++p is same as tw o expressions p=p+1 follow ed by x=*p.
(iv) x=++*p is sam e as tw o expressions *p=*p+1 follow ed by x=*p
C is consistent and regular in its approach to address arithm etic; its integration o f pointers, arrays,
and address arithm etic is one o f the strengths o f the language. Let us illustrate by w riting a
rudim entary storage allocator. There are tw o routines. The first, a l l o c (n ), returns a pointer to n
consecutive character positions, w hich can be used by the caller o f a l l o c for storing characters.
The second, a f r e e (p ), releases the storage thus acquired so it can be reused later. The routines
are ''rudim entary'' because the calls to a f r e e m ust be m ade in the opposite order to the calls m ade
on a l lo c . That is, the storage managed by a llo c and afree is a stack, or last-in, first-out. The
standard library provides analogous functions called m a llo c and free that have no such
restrictions.
The easiest implementation is to have a llo c hand out pieces of a large character array that we will
call a l l o c b u f . This array is private to a llo c and a fre e . Since they deal in pointers, not array
indices, no other routine need know the name of the array, which can be declared s t a t i c in the
source file containing a llo c and afre e , and thus be invisible outside it. In practical
implementations, the array may well not even have a name; it might instead be obtained by
calling m a llo c or by asking the operating system for a pointer to some unnamed block of storage.
The other information needed is how much of allocbuf has been used. We use a pointer, called
a l l o c p , that points to the next free element. When a llo c is asked for n characters, it checks to
see if there is enough room left in a llocbuf . If so, a llo c returns the current value of a l l o c p (i.e.,
the beginning of the free block), then increments it by n to point to the next free area. If there is
no room, a llo c returns zero. afree(p) merely sets a l lo c p to pif p is inside allocbuf .
#define ALLOCSIZE 10000 s t a t i c
char allocbuf[A L L O C S IZ E ];
s t a t i c c h a r * a llo c p = allocbuf;
c h a r * a llo c (in t n)
{
i f (allocbuf + ALLOCSIZE - a llo c p > = n) {
allocp += n;
return allocp - n;
} else
return 0;
}
v o id afree(char *p)
{
i f (p >= allocbuf&& p <allocbuf + ALLOCSIZE) allocp = p;
}
In general a pointer can be initialized just as any other variable can, though normally the only
meaningful values are zero or an expression involving the address of previously defined data of
appropriate type. The declaration
s t a t i c c h a r *allocp = allocbuf;
defines allocp to be a character pointer and initializes it to point to the beginning of allocbuf ,
which is the next free position when the program starts. This could also have been written
s t a t i c char *allocp = &allocbuf[0];
since the array name is the address of the zeroth element. The test
checks if there's enough room to satisfy a request for n characters. If there is, the new value of
allocp would be at most one beyond the end of allocbuf . If the request can be satisfied,
a llo c returns a pointer to the beginning of a block of characters (notice the declaration of the
function itself). If not, a llo c must return some signal that there is no space left. C guarantees that
zero is never a valid address for data, so a return value of zero can be used to signal an abnormal
event, in this case no space.
Pointers and integers are not interchangeable. Zero is the sole exception: the constant zero may be
assigned to a pointer, and a pointer may be compared with the constant zero. The symbolic
constant NULL is often used in place of zero, as a mnemonic to indicate more clearly that this is a
special value for a pointer. NULL is defined in <s t d i o .h>. We will use NULL henceforth. Tests
like
if (allocbuf + ALLOCSIZE - allocp>= n)
i f (allocbuf + ALLOCSIZE - a llo c p > = n) and i f
(p >= allocbuf&& p <allocbuf + ALLOCSIZE)
show several important facets of pointer arithmetic. First, pointers may be compared under certain
circumstances. If p and q point to members of the same array, then relations like ==, !=,
<, >=, etc., work properly. For example,
p < q
is true if p points to an earlier element of the array than q does. Any pointer can be meaningfully
compared for equality or inequality with zero. But the behavior is undefined for arithmetic or
comparisons with pointers that do not point to members of the same array. (There is one
exception: the address of the first element past the end of an array can be used in pointer
arithmetic.) Second, we have already observed that a pointer and an integer may be added or
subtracted. The construction
p + n
means the address of the n-th object beyond the one p currently points to. This is true regardless
of the kind of object p points to; n is scaled according to the size of the objects p points to,
which is determined by the declaration of p . If an i n t is four bytes, for example, the i n t will be
scaled by four.
Pointer subtraction is also valid: if p and q point to elements of the same array, and p<q, then q-
p+1 is the number of elements from p to q inclusive. This fact can be used to write yet another
version of s t r l e n :
in t s trle n (c h a r *s)
{
char *p = s;
w h ile (*p != ' \ 0')
p++;
Page 4
Address Arithmetic
If p is a pointer to som e elem ent o f an array, then p ++ increm ents p to point to the next element,
and p +=i increm ents it to point i elem ents beyond w here it currently does. These and sim ilar
constructions are the sim ples form s o f pointer or address arithm etic. All types o f arithm etic
operations are not possible w ith pointers. The valid operations that can be perform ed using
pointers are
(i) A ddition o f an integer to a pointer and increm ent operation.
(ii) Subtraction o f an integer from a ponter and decrem ent operation.
(iii) Subtraction o f a pointer from another pointer o f sam e type.
The arithm etic operations that cannot be perform ed on pointers are as follow s
(i) A ddition, m ultiplication and division o f tw o pointers.
(ii) M ultiplication betw een pointer and any number.
(iii) D ivision o f a pointer by any number.
(iv) A ddition o f float or double values to pointers.
The expression p+1 yields the correct m achine address for the next variable o f that type. O ther
valid pointer expressions:
p+i, ++p, p+=I, p-q
w here p-q represents the N o o f array elem ents betw een p and q.
Since a pointer is ju st a m em address, w e can add to it to traverse an array.
p+1 returns a ptr to the next array element.
Precedence level o f * operator and increm ent/decrem ent operators is sam e and their associativity
is from right to left. In reality, p+1 doesn’t add 1 to the m em ory address, it adds the size o f the
array element.
Suppose p is an integer pointer and x is an integer variable. N ow the m ain problem is to identify
how the follow ing pointer expressions given below are interpreted.
(i) x = *p++ is same as tw o expressions x = *p follow ed by p = p + 1.
(ii) x = (*p)++ is same as tw o expressions x = *p follow ed by *p = *p + 1.
(iii) x=*++p is same as tw o expressions p=p+1 follow ed by x=*p.
(iv) x=++*p is sam e as tw o expressions *p=*p+1 follow ed by x=*p
C is consistent and regular in its approach to address arithm etic; its integration o f pointers, arrays,
and address arithm etic is one o f the strengths o f the language. Let us illustrate by w riting a
rudim entary storage allocator. There are tw o routines. The first, a l l o c (n ), returns a pointer to n
consecutive character positions, w hich can be used by the caller o f a l l o c for storing characters.
The second, a f r e e (p ), releases the storage thus acquired so it can be reused later. The routines
are ''rudim entary'' because the calls to a f r e e m ust be m ade in the opposite order to the calls m ade
on a l lo c . That is, the storage managed by a llo c and afree is a stack, or last-in, first-out. The
standard library provides analogous functions called m a llo c and free that have no such
restrictions.
The easiest implementation is to have a llo c hand out pieces of a large character array that we will
call a l l o c b u f . This array is private to a llo c and a fre e . Since they deal in pointers, not array
indices, no other routine need know the name of the array, which can be declared s t a t i c in the
source file containing a llo c and afre e , and thus be invisible outside it. In practical
implementations, the array may well not even have a name; it might instead be obtained by
calling m a llo c or by asking the operating system for a pointer to some unnamed block of storage.
The other information needed is how much of allocbuf has been used. We use a pointer, called
a l l o c p , that points to the next free element. When a llo c is asked for n characters, it checks to
see if there is enough room left in a llocbuf . If so, a llo c returns the current value of a l l o c p (i.e.,
the beginning of the free block), then increments it by n to point to the next free area. If there is
no room, a llo c returns zero. afree(p) merely sets a l lo c p to pif p is inside allocbuf .
#define ALLOCSIZE 10000 s t a t i c
char allocbuf[A L L O C S IZ E ];
s t a t i c c h a r * a llo c p = allocbuf;
c h a r * a llo c (in t n)
{
i f (allocbuf + ALLOCSIZE - a llo c p > = n) {
allocp += n;
return allocp - n;
} else
return 0;
}
v o id afree(char *p)
{
i f (p >= allocbuf&& p <allocbuf + ALLOCSIZE) allocp = p;
}
In general a pointer can be initialized just as any other variable can, though normally the only
meaningful values are zero or an expression involving the address of previously defined data of
appropriate type. The declaration
s t a t i c c h a r *allocp = allocbuf;
defines allocp to be a character pointer and initializes it to point to the beginning of allocbuf ,
which is the next free position when the program starts. This could also have been written
s t a t i c char *allocp = &allocbuf[0];
since the array name is the address of the zeroth element. The test
checks if there's enough room to satisfy a request for n characters. If there is, the new value of
allocp would be at most one beyond the end of allocbuf . If the request can be satisfied,
a llo c returns a pointer to the beginning of a block of characters (notice the declaration of the
function itself). If not, a llo c must return some signal that there is no space left. C guarantees that
zero is never a valid address for data, so a return value of zero can be used to signal an abnormal
event, in this case no space.
Pointers and integers are not interchangeable. Zero is the sole exception: the constant zero may be
assigned to a pointer, and a pointer may be compared with the constant zero. The symbolic
constant NULL is often used in place of zero, as a mnemonic to indicate more clearly that this is a
special value for a pointer. NULL is defined in <s t d i o .h>. We will use NULL henceforth. Tests
like
if (allocbuf + ALLOCSIZE - allocp>= n)
i f (allocbuf + ALLOCSIZE - a llo c p > = n) and i f
(p >= allocbuf&& p <allocbuf + ALLOCSIZE)
show several important facets of pointer arithmetic. First, pointers may be compared under certain
circumstances. If p and q point to members of the same array, then relations like ==, !=,
<, >=, etc., work properly. For example,
p < q
is true if p points to an earlier element of the array than q does. Any pointer can be meaningfully
compared for equality or inequality with zero. But the behavior is undefined for arithmetic or
comparisons with pointers that do not point to members of the same array. (There is one
exception: the address of the first element past the end of an array can be used in pointer
arithmetic.) Second, we have already observed that a pointer and an integer may be added or
subtracted. The construction
p + n
means the address of the n-th object beyond the one p currently points to. This is true regardless
of the kind of object p points to; n is scaled according to the size of the objects p points to,
which is determined by the declaration of p . If an i n t is four bytes, for example, the i n t will be
scaled by four.
Pointer subtraction is also valid: if p and q point to elements of the same array, and p<q, then q-
p+1 is the number of elements from p to q inclusive. This fact can be used to write yet another
version of s t r l e n :
in t s trle n (c h a r *s)
{
char *p = s;
w h ile (*p != ' \ 0')
p++;
}
In its declaration, p is initialized to s , that is, to point to the first character of the string. In the
while loop, each character in turn is examined until the ' \ 0 ' at the end is seen. Because p
points to characters, p++ advances p to the next character each time, and p-s gives the number
of characters advanced over, that is, the string length. (The number of characters in the string
could be too large to store in an i n t . The header <s t d d e f . h>defines a type p t r d i f f t that is
large enough to hold the signed difference of two pointer values. If we were being cautious,
however, we would use siz e t for the return value of s t r l e n , to match the standard library
version. siz e t is the unsigned integer type returned by the s iz e o f operator.
Pointer arithmetic is consistent: if we had been dealing with f l o a t s, which occupy more storage
that char s, and if p were a pointer to f l o a t , p++ would advance to the next f l o a t . Thus we
could write another version of a l lo c that maintains f l o a t s instead of chars, merely by changing
char to f l o a t throughout a l l o c and a f r e e . All the pointer manipulations automatically take
into account the size of the objects pointed to.The valid pointer operations are assignment of
pointers of the same type, adding or subtracting a pointer and an integer, subtracting or comparing
two pointers to members of the same array, and assigning or comparing to zero. All other pointer
arithmetic is illegal. It is not legal to add two pointers, or to multiply or divide or shift or mask
them, or to add f l o a t or double to them, or even, except for void *, to assign a pointer of one
type to a pointer of another type without a cast.
return p - s;
Read More