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

Module04 ClassNotes

Uploaded by

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

Module04 ClassNotes

Uploaded by

Geay Peter
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 23

RCS 210: PROGRAMMING IN C

(a.k.a. Programming in ANSI / ISO C)

Module 04 -- Pointer Types and Debugging


Techniques in C

“Code softly and carry a big debugger.”


-- anon.
4-1
Arrays and Pointers in C
• Array name is the address of 0th element
• Pointer arithmetic
• x[i] is equivalent to *(x + i)
• Array name is effectively a constant pointer
• Multi-dimension arrays
• Arrays as parameters

4-2
Array name is the address of 0th element
• an array name in C corresponds to the base address of the array
• another way of saying this is that for the array:
int x[10];
the expression (x) is equivalent to (&x[0])
• an array name is therefore effectively a pointer:
– the type that x points to is the type of the elements of the array
• i.e. x is effectively of type int *
– array names however are a constant and can not be modified:
• x = &y; is illegal!

4-3
Pointer arithmetic
• addition and subtraction (only) are allowed with pointers
• pointer arithmetic is “aware” of the size of the type pointed to
so that, for example, adding 2 to a pointer value actually adds:
(2 * sizeof(<type-pointed-to>) )
• this means we can use pointer arithmetic to “step through” an
array, regardless of the type of the array element ...

4-4
Pointer arithmetic

float table[4] = {2.24, 4.24, 3.24, -2.1};


float *fp;
float sum = 0.0; table
int j; [0] [1] [2] [3] sum j
fp = table; 2.24 4.24 3.24 -2.1 7.62 4
for (j=0; j < 4; j++, fp++)
sum += *fp;

/* normally we might fp fp fp fp fp
* just do:
* sum += table[j];
*/
4-5
Pointer arithmetic
• another way ...

float table[4] = {2.24, 4.24, 3.24, -2.1};


float *fp;
float sum = 0.0;
for (fp=table; fp < table + 4; fp++)
sum += *fp;

4-6
Pointer arithmetic
• and yet another way ...

float table[4] = {2.24, 4.24, 3.24, -2.1};


float *start = table, *end = table + 4;
float sum = 0.0;
for ( ; start < end; start++)
sum += *start;

4-7
Pointer arithmetic
• and yet another way … using our pointer as though it was an
array ...

float table[4] = {2.24, 4.24, 3.24, -2.1};


float *fp = table;
float sum = 0.0;
int j;

for (j=0; j < 4; j++) for (j=0; j < 4; j++)


sum += fp[j]; sum += *(fp + j);

4-8
Pointer arithmetic
• … one more time … who needs pointers anyway?

float table[4] = {2.24, 4.24, 3.24, -2.1};


float sum = 0.0;
int j;

for (j=0; j < 4; j++) for (j=0; j < 4; j++)


sum += table[j]; sum += *(table + j);

4-9
x[i] is equivalent to *(x + i)
• the previous example shows that:
table[j] is equivalent to *(table + j)
• this is true for any pointer, including array names
• this special relationship between arrays and pointers in C says
that for any array of any type:
x[i] is equivalent to *(x + i)
(x + i) is the address of the ith element of x
x[i] is the (dereferenced) value at location (x + i)

4-10
Array name is a constant pointer
• and just a reminder … that one important difference between an
array name and a pointer variable is:
– an array name is a constant pointer
– i.e. it can not be altered … i.e. ...

int x[10], *ptr;

ptr = x; /* is legal (and useful) */


x = ptr; /* is illegal - compiler error! */

4-11
Arrays as parameters
• we can see now why call-by-value (where a copy of the data is made)
is not possible with array names:
int numList[SIZE] = { 1, 2, 3, 4, 5 };
int sum;
sum = add(numList); /* equivalent to ... */
sum = add(&numList[0]);
• i.e. numList is an array name which evaluates to:
&numList[0]
… therefore ...

4-12
Arrays as parameters
• function add would look like either :

int add(int *nums) int add(int nums[])


{ {
int total = 0, j; int total = 0, j;
for (j=0; j<SIZE; j++) for (j=0; j<SIZE; j++)
total += *(nums + j); total += nums[j];
return total; return total;
} }

4-13
Multi-dimension arrays
• these properties extend to multi-dimension arrays
int matrix[3][4];
int *cellA, *cellB; cellA
int (*rowA)[4], (*rowB)[4];
cellA = &matrix[1][2]; [0] [1] [2] [3]
cellB = cellA + 3;
rowA [0]
rowA = &matrix[1]; [1]
rowB = rowA + 1; [2]
rowB
(*rowB)[2] = *cellA;

cellB
4-14
Multi-dimension arrays
• or … viewing the 2D array as an array of arrays ...

cellA cellB

[0][0] [0][1] [0][2] [0][3] [1][0] [1][1] [1][2] [1][3] [2][0] [2][1] [2][2] [2][3]

Row [0] Row [1] Row [2]

rowA rowB
4-15
Multi-dimension arrays
• the equivalence between array indexing and pointer
dereferencing still applies ...
int matrix[ROWS][COLS];
int i, j, sum = 0;
for (i=0; i < ROWS; i++)
for (j=0; j < COLS; j++)
sum += matrix[i][j];

Alternatives:
sum += *(matrix[i] + j);
sum += *(*(matrix + i) + j);
sum += (*(matrix + i))[j]; 4-16
Multi-dimension arrays as parameters
Calling function: int matrix[3][4];
int sum;

sum = matrixSum(matrix);

Equivalent function definitions:

int matrixSum(int mat[][4])


{ ...
total += mat[i][j]; int matrixSum(int (*mat)[4])
... { ...
} total += mat[i][j];
...
}
4-17
Multi-dimension arrays as parameters
Calling function: int matrix[3][4];
int sum;

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


sum = vectorSum(matrix[i]);

Equivalent function definitions:


int vectorSum(int vector[]) int vectorSum(int *vector)
{ … { …
total += vector[j]; total += vector[j];
… …
} }

4-18
Debugging
• Coding your algorithm is not the end of the software
development process; next comes testing and debugging.
• You can very dramatically reduce the complexity of debugging
by coding-testing-debugging incrementally (ie. just a “few”
lines of code at a time)
• Always, always indent your program consistently. If you change
the program, change the indentation to match. It's worth the
trouble. Debugging is aided enormously by easily readable
code.
• Take the time to understand the error before you try to fix it.
Programming is not an experimental science.

4-19
Testing
• When your program compiles without error, you are still not likely
to be done.
• You must test your programs carefully in order to find bugs.
• Your program must work correctly. The goal is not to get the right
output for just the few sample inputs that you may have been
provided with, but to get the right output for all valid inputs. When
presented with invalid input, your program should respond with
appropriate error messages and/or directions, and certainly should
not “crash”.
• Debugging is a skill that, like other aspects of programming,
requires practice to master. So don't be afraid of bugs. Learn from
them.
4-20
Debugging
• One essential debugging skill is the ability to read source code
and to follow it the way the computer does (ie. mechanically,
step-by-step) to see what it really does. This is hard.
• Often, it's a problem just to find the part of the program that
contains the error. Most programming environments come with
a debugger, which is a program that can help you find bugs.
• Older (but often as effective) approaches to debugging include
inserting (temporarily) debugging statements into your program.
• Remember: If you are absolutely sure that everything in your
program is right, and if it still doesn't work, then one of the
things that you are absolutely sure of is wrong!

4-21
Debugging Techniques
• Incrementally code-test-debug just a few lines at a time
– start with say 6 lines at a time, this can be increased with experience.
• Use test-drivers to test functions and/or modules in isolation
from the rest of the main program.
• Use function stubs for incomplete functions.
• Use program checkers such as lint, lclint, …
• Use debuggers, where available, for features including
breakpoints, single-step execute, watch variables, …
• Use dynamic memory use checkers, where available, for
features including memory leak detection, buffer overrun
detection, …
4-22
Kernighan & Pike on Debugging

• “Another effective [debugging] technique is to explain your


code to someone else. This will often cause you to explain the
bug to yourself. Sometimes it takes no more than a few
sentences, followed by an embarrassed "Never mind. I see
what's wrong. Sorry to bother you." This works remarkbly well;
you can even use non-programmers as listeners. One university
computer center kept a teddy bear near the help desk. Students
with mysterious bugs were required to explain them to the bear
before they could speak to a human counselor.”
--"The Practice of Programming" by Brian W Kernighan & Rob Pike

4-23

You might also like