Title: Introduction to C Lecture 5: Arrays, Pointers and Strings
1Introduction to CLecture 5 Arrays, Pointers and
Strings
2One-dimensional arrays
- An array stores a set of data of the same type.
Declaration - Â
- int gradesize / space for a0, ....
asize-1 allocated. - Â
- Note indexing of elements always starts at zero,
so the first entry is grade0 not grade1. - It is sometimes useful (in simple problems where
you know the size in advance) to define the size
of an array as a symbolic constant - Â
- define NO_OF_POINTS 100
- Â
- int aNO_OF_POINTS
- Â
- The array is then typically processed with a for
loop - Â
- for (i 0 i lt NO_OF_POINTS i)
- sum ai
- Â
- Changes in size are then taken care of all in one
place. - Â
3One-dimensional arrays, contd
- The index i is referred to as a subscript.
Arrays can be initialized - Â
- float f5 0.0, 1.0, 2.0, 3.0, 4.0
- Â
- If some but not all elements are initialized,
others are set to zero. External and static
arrays are initialized to zero by default anyway
automatic arrays are not, although some compilers
do so. Arrays can be declared without a size,
and the size is set to the number of
initializers - float f 0.0, 1.0, 2.0, 3.0, 4.0
- is equivalent to the above. This works with
character arrays too, although an alternative is
available - Â
- char s abc
- is equivalent to
- char s a, b, c, \0
- The \0 at the end here is the end-of-character-st
ring symbol. - Â
- A common error is to allow the program to access
elements beyond the end of the array e.g. a6
in a six-element array. (Remember it starts at
zero!). It is your job to ensure that subscripts
stay within bounds. - Â
4Pointers
- Variables are stored in particular locations, or
addresses, in memory if v is a variable then v
is the address in memory of its stored value.
Pointers are used to access these memory
locations directly. - The declaration int pdeclares that p is a
pointer to the address of an int type variable.
If x is an integer, for example, we can then
set p xLikewise, if a is an array of
integers, p a0 can be used to point to it. - If we know that p holds the address of a
variable, we can use the indirection or
dereferencing operator to give the value that
is held at that address. (Think of this as the
inverse of and dont confuse it with the
used in the int p declaration to tell the
compiler that p is a pointer). - Lets look at an example.
5Pointers
- int a 1, b 2, p
- At this point, a, b and p are stored in memory as
- Â
- Now we assign
- p a
- and we obtain the following
- If we now assign
- b p
- this gives b the value stored at the address of
a, i.e. it is equivalent to b a. - Â
6Pointers, contd.
- Exercise
- int i 3, j 5, p i, q j, r
- double x
- Give values for
- p
- q
- j p
- j i
- j/ p
- Notice the careful use of a space between / and
to avoid p /q, which would have looked like the
start of a comment... (This nasty bug cost me
many hours the first time I did it...)
7Pointer to void
- void is a generic pointer, and can be assigned
to any variable type. However, for good practice
you should always type cast it into the
appropriate pointer type. Suppose for example we
have - int p
- void v
- Suppose then that v ends up pointing to some
integer quantity, and we want p to point there
too. We would say p (int ) v This makes
sure that the pointer types agree properly.
8Call-by-reference
- When functions are called in C, the arguments are
evaluated and their values are passed down to the
function the variables themselves are not
affected. If we want to change the variables in
the calling environment, we have to use pointers
and send down the address of the variables. - We do this by
- Declaring a function parameter to be a pointer
- Passing an address as an argument when the
function is called. - Using the dereferenced pointer in the function
body - Dont know what Im talking about? OK, example
coming up...
9Call-by-reference
- include ltstdio.hgt
- void swap(int , int )
- /----------------------------------/Â
- int main(void)
-
- int i 3, j 5
- Â
- swap (i, j)
- printf(d d\n, i, j) / 5 3 is printed /
- return 0
-
- /----------------------------------/Â Â
- void swap(int p, int q)
-
- int tmp
- tmp p
- p q
- q tmp
-
10Call-by-reference
Function parameters are pointers (to int)
- include ltstdio.hgt
- void swap(int , int )
- /----------------------------------/Â
- int main(void)
-
- int i 3, j 5
- Â
- swap (i, j)
- printf(d d\n, i, j) / 5 3 is printed /
- return 0
-
- /----------------------------------/Â Â
- void swap(int p, int q)
-
- int tmp
- tmp p
- p q
- q tmp
-
11Call-by-reference
Function parameters are pointers (to int)
- include ltstdio.hgt
- void swap(int , int )
- /----------------------------------/Â
- int main(void)
-
- int i 3, j 5
- Â
- swap (i, j)
- printf(d d\n, i, j) / 5 3 is printed /
- return 0
-
- /----------------------------------/Â Â
- void swap(int p, int q)
-
- int tmp
- tmp p
- p q
- q tmp
-
Pass the addresses of the variables when
calling the function
12Call-by-reference
Function parameters are pointers (to int)
- include ltstdio.hgt
- void swap(int , int )
- /----------------------------------/Â
- int main(void)
-
- int i 3, j 5
- Â
- swap (i, j)
- printf(d d\n, i, j) / 5 3 is printed /
- return 0
-
- /----------------------------------/Â Â
- void swap(int p, int q)
-
- int tmp
- tmp p
- p q
- q tmp
-
Pass the addresses of the variables when
calling the function
Inside the function, use the dereference
operator to access the values stored at the
addresses you sent down
13Call-by-reference
Function parameters are pointers (to int)
- include ltstdio.hgt
- void swap(int , int )
- /----------------------------------/Â
- int main(void)
-
- int i 3, j 5
- Â
- swap (i, j)
- printf(d d\n, i, j) / 5 3 is printed /
- return 0
-
- /----------------------------------/Â Â
- void swap(int p, int q)
-
- int tmp
- tmp p
- p q
- q tmp
-
Pass the addresses of the variables when
calling the function
Inside the function, use the dereference
operator to access the values stored at the
addresses you sent down
Exercise Change this program (.../lect5/swap.c)
and make it rotate three variables i ? j, j ? k
and k ? i.
14Relationship between Arrays and Pointers
- An array name is simply a pointer to the start of
the array! Thus, pointers and arrays are closely
linked. If a is an array, i is an int, and p is
a pointer, then ai is equivalent to (a
i) pi is equivalent to (p i) p a is
equivalent to p a0 p a1 is equivalent
to p a1 - Expressions such as p i and a i are examples
of pointer arithmetic, of which more later.
15Relationship between arrays and pointers, contd
- We can use the following code (where p is a
pointer) to sum an array a - for (p a p lt aN p)
- sum p
- Or this
- for (i 0 i lt N i)
- sum (a i)
- Or this
- for (p a, i 0 i lt N i)
- sum pi
- Note however that because a is a constant
pointer, expressions such as - a p a a 2 aare illegal. We cannot
change the value of a in the way that we can for
p.
16Pointer arithmetic
- One of the powerful features of C. If p is a
pointer to a particular type, then p1 yields the
correct machine address of the next variable of
that type. So - If p (a pointer to int) happens to point to
address 1734, then p1 will point to address
1738. If p (still 1734) were a pointer to char
instead, p1 would point to address 1735 if p
were a pointer to double, p1 would point to
address 1742. And so on. - If p and q are both pointing to elements of an
array, p - q yields the int value representing
the number of array elements between p and q.
Exampledouble a2, p, qp a / points
to base of array / - q p 1 / equiv. q a1 /
- printf(d\n, q - p) / 1 is printed /
- printf(d\n, (int)q - (int)p) / 8 is printed
/
17Exercise Bubble sort
- This is an extremely inefficient sorting
algorithm! Code is in .../lect6/bubsort.
Compile and run a program containing this
function then go through the code, adding
comments to ensure that you understand how it
works. (Then forget you ever knew it, and work
with a better algorithm instead). - Â
- void swap(int , int ) / same swap function
as before / - Â
- void bubble(int a, int n) / n is size of a /
-
- int i,j
-
- for (i 0 i lt n-1 i)
- for (j n - 1 j gt i --j)
- if (aj-1 gt aj)
- swap(aj-1,aj)
-
- Â
- Note that the swap function call could also have
been written - swap(a j - 1, a j)
18Dynamic Memory Allocation
- We cannot always know in advance how big an
array, for example, might be necessary in running
a program. There are two ways around this - Set aside huge amounts of memory when writing the
program, and hope that more than this is never
needed. - Take as much memory as is needed on the fly.
- The latter is obviously much more intelligent and
flexible, and in C its easy to do. If you need
memory to store n array elements, each of which
is (say) an integer, you do this - Â
- a (int ) calloc(n, sizeof(int))
19Dynamic Memory Allocation, contd
- So, in short a (int ) calloc(n,
sizeof(int)) where int can be replaced with
char, double, or anything else. - There is also an alternative a (int )
malloc(total_size) where total_size n
element_size. - Note that space allocated in this way must be
given back explicitly once finished with,
by free(a) / where a is the pointer name
/before exiting the function. If the pointer
is NULL, there is no effect if it is the base
address of the space allocated by calloc( ),
malloc( ) or realloc( ) the space is deallocated
if it is anything else there is a
system-dependent error. If you dont give the
memory back, but keep on taking more, you will
eat it all until the program crashes.
20Example
- malloc_ex.c in usual place... includes lines
- Â
- a malloc(nsizeof(int))
- / allocates space for array a /
- fill_array(a,n) / fill with random nos
1-10 / - wrt_array(a,n) / writes out the array
/ - printf("sum d\n\n", sum_array(a,n))
- free(a)
- Â
- Try it and see!
- (Notes about this code
- srand(time(NULL)) seeds the random-number
generator - rand() 19 takes the remainder when a random
number is divided by 19, to give a random number
between 0 and 18, so rand() 19 9 gives a
random number between 9 and 9)
21Another example merge
- / Merge a of size m and b of size n into
c from KP / - include "mergesort.h
- void merge(int a, int b, int c, int m, int
n) - int i 0, j 0, k 0
- while (i lt m j lt n) ck((ai lt bj)?
aibj) - while (i lt m) ck ai / pick up any
remainder / - while (jltn) ck bj
-
- This is the basis for a standard sorting routine,
called mergesort. Well be looking at it in the
problem sheet and in the weeks to come.