Chapter 4
Pointers
4.1 Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.2 The Swap Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.3 Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.4 The Swap Function Revisited . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.5 Type Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
4.6 Arrays and Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
4.7 Type Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4.8 Pointer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.9.1 Swap Function 1 .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.9.2 Swap Function 2 .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.9.3 Swap Function 3 .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.9.4 Swap Function 4 .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.9.5 Swap Function 5 .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.9.6 15,552 Variations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.10 Answers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.10.1 Swap Function 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.10.2 Swap Function 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.10.3 Swap Function 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.10.4 Swap Function 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.10.5 Swap Function 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.1 Scope
Chapter 2 described several rules. One of those rules was that each function can see only
its own frame. This is called scope. A new scope is created every time a pair of { and } is
used. This could be inside of a function body, for example, an if statement, or a while loop.
The following example shows two scopes:
void f( i nt a , i n t b)1
{2
/* this is a scope , call it X */3
int i;4
for (i = 0; i < a + b ; i ++)5
{6
/* this is another scope , call it Y */7
int j;8
}9
}10
39
40 Intermediate C Programming
In the scope marked X (in the comments), a and b are arguments and i is a local
variable. Another scope called Y is created inside of X. Scopes are always nested inside of
each other like this. Variables from outer scopes are still accessible, so scope Y can “see” a,
b, and i. A local variable j is created inside of scope Y and is accessible only inside scope
Y; scope X cannot “see” j.
The following example has three scopes: X, Y, and Z. The arguments a and b in f1
have nothing to do with the arguments of a and b in f2 because they are in different and
non-overlapping scopes: f1 is not nested in f2 or vice versa.
The variable j is in the inner scope, and can only be “seen” between the { and } of the
for loop.
void f1 ( i n t a , int b)1
{2
/* this is a scope , call it X */3
int i;4
for (i = 0; i < a + b ; i ++)5
{6
/* this is another scope , call it Y */7
int j;8
}9
}10
11
void f2 ( i n t a , int b)12
{13
/* this is a scope , call it Z */14
f1 (a + b , a - b) ;15
/* RL A */16
}17
It is legal to create another variable of the same name in an inner scope, like u.
void f1 ( i n t u , int v)1
{2
/* this is a scope , call it X */3
int i;4
for (i = 0; i < u + v ; i ++)5
{6
/* this is another scope , call it Y */7
int j;8
int u; /* shadow variable */9
}10
}11
In the inner scope Y, we create a new variable called u. Please note that Y already has
an argument called u. By adding the type int in front of u, a new variable is created. This
function now has two variables both called u in the overlapping scopes (Y is nested inside
of X). This makes the u in Y a shadow variable of the u in X. These two variables have two
different memory addresses. Modifying the u in scope Y does not change the u in scope
X. Shadow variables are considered bad programming style because they make programs
difficult to understand, and can introduce subtle errors. Consider the following example:
void f1 ( i n t u , int v)1
{2
/* this is a scope , call it X */3
Pointers 41
int i;4
u = 27;5
for (i = 0; i < u + v ; i ++)6
{7
/* this is another scope , call it Y */8
int u; /* shadow variable because of int */9
u = 5;10
}11
/* u is 27 even though it was as signed to 5 two lines12
earlier */13
}14
The value of u is 5 just above the closing brace (line 11) that encloses scope Y. After
leaving Y, the value of u is 27 because the outer u was never changed. This can make the
program confusing, and confusing programs are error-prone. Fortunately most compilers
make it is easy to detect shadow variables. For example, gcc compiler warns about shadow
variables when you add -Wshadow to gcc.
4.2 The Swap Function
A function can return only one value. The returned value can be used to modify one
thing in the caller. For example,
int f1 ( in t a , in t b )1
{2
return (a + b) ;3
}4
5
void f2 ( void)6
{7
int s;8
s = f1 (2 , 37) ;9
/* RL A */10
}11
In the function f2, we see s becomes the sum of 2 and 37. By calling f1 we are able
to change one variable in the caller f2. What can we do if we want to change two or more
variables in the caller? Suppose we want to write a “swap function”,
void swap ( i n t x , i n t y )1
{2
3
/* do something to swap x and y */4
5
}6
7
void f2 ( void)8
{9
int a = 2;10
int b = 37;11
42 Intermediate C Programming
swap (a , b);12
/* RL A */13
}14
Can this swap function work?
void swap ( i n t x , i n t y )1
{2
int z = x;3
x = y;4
y = z;5
}6
When the swap function is called, the values of a and b are copied to the arguments x and
y. The call stack is shown below.
Frame Symbol Address Value
swap
z 106 -
y 105 37
x 104 2
Return Location 103 line 13
f2
b 102 37
a 101 2
The value of x is stored in a temporary variable z. Then y’s value is assigned to x and
z’s value is assigned to y. After these three steps, x has y’s old value and y has x’s old value
(through z). After finishing line 5 in swap and before the top frame is popped, this is the
call stack:
Frame Symbol Address Value
swap
z 106 2
y 105 2
x 104 37
Return Location 103 line 13
f2
b 102 37
a 101 2
Inside swap, the values of x and y have been swapped. As explained in Chapter 2, when
swap finishes, the top frame is popped. After the top frame is popped, the call stack becomes
Frame Symbol Address Value
f2
b 102 37
a 101 2
The swap function was called and finished, and the values of a and b have not changed.
This swap function does not work. C programs use “call-by-value” when calling functions
That means that values are copied from the caller to the arguments of the called function
(i.e., callee). This is the only way to call functions in C. Java and C++ have call-by-value
and call-by-reference but C only uses call-by-value.
Does this mean it is impossible to write a swap function?
Pointers 43
4.3 Pointers
C solves this problem by creating the concept of pointers. A pointer is a variable (or an
argument) whose value is a memory address. To create a pointer, add * after the type.
type * ptr ; // ptr is a pointer , meaning its value is a1
memory address2
This creates a pointer called ptr. Its value is an address. At that address is stored a
value of the given type. This may seem abstract so let us see some concrete examples:
int * iptr ;1
char * cptr ;2
double * dptr ;3
name value at that address
iptr an address an integer
cptr an address a character
dptr an address a double-precision floating-point number
In each case, the pointer stores a memory address. Chapter 2 said programmers cannot
control addresses. How can a program obtain valid addresses? C provides special syntax for
precisely that purpose: by adding an & in front of a variable. For example,
int a = -61; // a is an integer1
int * iptr ; // iptr is a pointer2
iptr = & a; // iptr s value is as a d d r e s s3
Symbol Address Value
iptr 101 100
a 100 61
Section 2.3.6 prints the addresses of two variables a and c. It shows that the addresses
change when the same program runs again. By using an ampersand (&) in front of a, iptr’s
value changes every time the program runs. Please remember that a programmer can
change variables’ values but a programmer cannot change variables’ addresses.
You may want to ask why this example uses 100 for a’s address but the addresses in
Section 2.3.6 are much larger values. In order to make the book easier to read, the book
uses small addresses instead of the much larger addresses that are common on modern
computers.
How are pointers useful? First, just like any other variable type, two pointers can have
the same value.
int a = 632;1
int c; /* c s value is garbage now */2
c = a; /* c s value is the same as a s value */3
int * iptr1 ; /* iptr1 s value is garbage now */4
int * iptr2 ; /* iptr2 s value is garbage now */5
iptr1 = & a ; /* iptr1 s value is as address */6
iptr2 = iptr1 ; /* iptr2 and iptr1 have the same value */7
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset