sections in this module | City
College of San Francisco - CS270 Computer Architecture Module: MIPS-V |
module list |
More
on Pointers
In a previous section we discussed the C construct
char *message = "Computer Architecture is fun!"
where message is a static variable. We said that a compiler will generate an asciiz string for the message, a temporary label, then initialize a variable message with the address of the temporary label:
Now all we must do to use the string is to load the pointer
message and manipulate it. This is easy for static strings. But
what happens when the character string appears as an automatic
(local) variable:
Since strings are considered to be constants, the string itself can be static. Thus, this part of the code is the same
.Lmessage: .asciiz "Computer Architecture is fun!"
The pointer, however, must be allocated on the stack and thus must be initialized by code that is executed on entry to the function:
When a function is called, code like this must be executed for
any local variables that are initialized.
Multi-dimensional Arrays
Depending on the language, multi-dimensional arrays are stored in linear memory with the last (called row-major order for a two-dimensional array) or the first (column-major order) index increasing sequentially as the individual cells are stored. That's a mouthful. Let's look at the example for C-style two-dimensional arrays, which use row-major order:
int arr[2][3];
The elements of this array would be placed in-memory in this sequence:
arr[0][0], arr[0][1], arr[0][2], arr[1][0], arr[1][1], arr[1][2]
in other words, a row at a time. This is keeping with C's idea
that a two-dimensional array as that above is really an array of [
two ] arrays [ of three elements each ].
Of course, this arrangement in memory is the same as it would be for a single-dimensional array of 6 elements. If we call the corresponding array sarr[6], then locating an element of arr is really translating the indices of arr to the index of sarr.
Let's lay them out together to see what I mean
arr[0][0] | arr[0][1] | arr[0][2] | arr[1][0] | arr[1][1] | arr[1][2] |
sarr[0] |
sarr[1] |
sarr[2] |
sarr[3] |
sarr[4] |
sarr[5] |
Let's take an arbitrary two-dimensional array int
arr[rows][cols]. To find indx, where sarr[indx] will be located at
the same offset as arr[i][j], we would use indx = (i*cols + j).
Once we have indx, we can access the array element by simply
multiplying by the size of the base
type, here int.
Arrays of strings
An array of strings is really an array of pointers to strings,
and is handled the same as any scalar array. The only difference
is its base type is char *. Remember, there is no difference
between an array of char *'s and an array of anything else. The
only difference is how you use the elements!
Consider the following simple program messages.c
We should all be able to write this is MIPS code. But how about a simple modification
char
*messages[3] = { "message1", "message2", "message3" };
void outmessages(char **
themessages,int n) {
int i;
for
(i=0;i<n; i++)
puts(*themessages++);
}
main() {
outmessages(messages, 3);
}
Can you rewrite messages.c to use the NULL (0) pointer in the
declaration
[ We will write the MIPS code for a similar program in the Problems page for this module. ]
Function Pointers
A function pointer is simply a pointer that is initialized to the
address of a function.
Suppose you want to call the function myfunc. There are three ways to write code for this call:
to call a function that is "close" |
to call a function that is "far away" |
using a function pointer |
jal
myfunc |
la
$t0,myfunc jalr $t0 |
#if
you want to initialize #funcptr statically .data funcptr: .word myfunc #or at runtime la $t0,myfunc
#then at the callsw $t0,funcptr lw $t0,funcptr
jalr $t0 |
A basic, but well-known, use of a function pointer is the qsort package in the C library. As many of you know, the qsort algorithm (and any sorting algorithm) is independent of the data being sorte so long as a mechanism is provided to compare two data items. This is provided to qsort() by giving it a function pointer. Here is the prototype
Here, base is a pointer to an array of nmemb elements. Each element is size bytes long. compar is a pointer to a function that can be passed two [pointers to] elements to compare them. It returns -1, 0, or +1 depending on whether the first element it is passed compares less than, equal, or greater than the second.
Here is an example of qsort used to sort an integer array ia
NOTE: there is some extra crap needed in this program to get the
compiler to stop complaining, but the program as listed below
compiles and runs correctly on linux, in spite of the warnings. I
didn't want to confuse the issue with the required casts.
In this example, the address of compare_ints is passed to qsort
as a function pointer. In the qsort routine, the function would be
called indirectly, passing it the address of two array elements
that it wants to compare.
At the high-level-language level, the compiler ensures that the function being passed is 'compatible' with the function required by qsort. It does this through argument typing. At the assembler level, of course, no such hand-holding occurs, and the programmer is responsible for ensuring the function call occurs correctly.
The C code for this version (iasort.c) and the version that
compiles without warnings (iasortX.c) is in the online/mipsIV
directory. There is no MIPS code, as we do not have code for a
qsort function.
Hopefully, we will have sufficient time to write a similar program in-class.
Prev | This page was made entirely
with free software on linux: the Mozilla Project and Openoffice.org |
Next |