| CompOrg Fall 2005 Lab |
|   CompOrg Home   |   p1   |   p2   |   p3   |   p4   |   p5   |   segvhunt   |   Hints/Suggestions |
This lab involves playing with a number of C programs to solve some problems involving pointers. There are 5 different problems, work on as many as you can. If you are a pointer guru, solve all the problems and make sure you get checked off before you leave...
Each program has instructions at the top. Each of these files are listed below (you can cut-and-paste), the files are also available in ~hollingd/public/lab3 on the cs machines, the following command would copy the file p1.c from ~hollingd/public/lab3 to your current working directory:
cp ~hollingd/public/lab3/p1.c p1.c
IMPORTANT!: Ask for help if you don't understand something, some of the issues may not be obvious if you have not done lots with pointers.
/* p1.c 1. find out (add code to print out) the address of the variable x in foo1, and the variable y in foo2. 2. add code to main that calls foo3 after the call to foo1 and before the call to foo2. Rerun the program and see what happens. Can you explain this? */ #include <stdio.h> void foo1(int xval) { int x; x = xval; /* print the address and value of x here */ } void foo2(int dmy) { int y; /* print the address and value of y here */ } void foo3(char *s, int len) { int i,j,k; i=len+3; j=len+4; } int main() { foo1(3); /* foo3("Hi Dave",5); */ foo2(12); }
/* p2.c 1. test the function append by compiling and runing the program. Fix the problem (there are many ways to fix the problem, ask for help if you can't figure out what the problem is). 2. Rewite append so that it uses pointers instead of array syntax (instead of s1[i], use *s1, etc). Once again, ask for help if you don't know how to do this! 3. Rewrite append so that it uses the library functions strcpy and strcat (at the command prompt type "man strcpy" or "man strcat" for details about these functions. You will need to add "#include <string.h>" to your program to tell the compiler about these functions. */ #include <stdio.h> /* function append appends two strings and returns the result (as a pointer to a new string) won't work unless the strings are no larger than 10 chars each */ char *append(char *s1, char *s2) { char both[25]; int i,j; if ((strlen(s1)>10) || (strlen(s2)>10)) { printf("Invalid string length (too big)\n"); return(NULL); } i=0; /* copy the first string to both */ while (s1[i]!=0) { both[i] = s1[i]; i++; } /* now append the second string */ j=0; while (s2[j]!=0) { both[i] = s2[j]; i++; j++; } return(both); } int main() { char *s = append("Hello ", "World"); if (s != NULL) printf("Result is %s\n",s); return(0); }
/* p3.c The program below can be used to determine the size of a 'char' variable. By using pointer arithmetic we can find out what the value of 's' is and the value of 's+3'. Since s is a pointer, this addition involves pointer arithmetic: adding one to a pointer makes the pointer point to the next element (regardless of the data type it points to). For a pointer to a char, adding 3 really just means adding 3 to the address, but this is only because each char is 1 byte. If we have a pointer to an int, and add 1 to that pointer, the resulting address is the address of the next int in memory, so it will be the initial address + the size of an int (in bytes). 1. compile and run the program and see what it prints out. 2. Write some code that does pointer arithmetic with a pointer to an int and determine how big an int is. 3. Same idea - figure out how large the datatype double is by using pointer arithmetic and printing out a pointer before and after adding 3. */ #include <stdio.h> int main( ) { char *s="abcdefghijklmnopqustuvwxyz"; printf("s is %d %08x\n",s,s); printf("The string at s is %s\n",s); /* Pointer arithmetic - see what s+3 is */ s = s+3; printf("s is %d %08x\n",s,s); /* and what is stored there (as a string) */ printf("The string at s is %s\n",s); }
/* p4.c 1. create a program that prints out the ASCII encoding of all the alphabetic characters and the space character ' '. You can print the ascii encoding of a char c with something like this: printf("%c %2d 0x%02x\n",c,c,c); Note that you can do things like this: char c; for (c='a'; c<='z';c++) { ... } You need the output from this program to solve the question below. 1. For the source code in this file, predict the value of i that is printed. Test your solution by compiling and runing the program, iterate until you can explain the result. Note that you need to determine the address of s and the address of i (or at least the relative difference)! 2. fix the problem (make it so that it prints the correct value of i: "i is 0"). */ #include <stdio.h> #include <string.h> /* needed for strcpy */ int main() { int i; char s[8]; i=0; strcpy(s,"Pointers are lots of fun\n"); printf("S is %s\n",s); printf("i is %d\n",i); return(0); }
/* p5.c
swap_nums seems to work, but not swap_pointers. Fix it.
*/
#include <stdio.h>
void swap_nums(int *x, int *y) {
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
void swap_pointers(char *x, char *y) {
char *tmp;
tmp = x;
x = y;
y = tmp;
}
int main() {
int a,b;
char *s1,*s2;
a = 3; b=4;
swap_nums(&a,&b);
printf("a is %d\n",a);
printf("b is %d\n",b);
s1 = "I am s1 the great";
s2 = "s2 rules";
swap_pointers(s1,s2);
printf("s1 is %s\n",s1);
printf("s2 is %s\n",s2);
return(0);
}
/* seghunt.c
find and eliminate all code that generates segv
*/
#include <stdio.h>
int main() {
char **s;
char foo[] = "Hello World";
*s = foo;
printf("s is %s\n",s);
s[0] = foo;
printf("s[0] is %s\n",s[0]);
return(0);
}
| Hints |
If you are not comfortable with pointers, you might try the suggestions below to work through things.
Draw a table as a representation of the memory of the computer that is used by your process. Something like this:
Assume each cell in your picture can hold a word (32 bit int or a pointer). Make up some addresses and label the cells with the addresses. Something like this:
| 100 | |
| 104 | |
| 108 | |
| 112 | |
| 116 | |
| 120 | |
| ... |
For each variable in the C function you are working with, assign
the variable to some memory location. For example, we could say that
the variable char *s is stored in memory location 104
and the variable int i is stored in memory location
112:
| 100 | |
| 104 | value of s |
| 108 | |
| 112 | value of i |
| 116 | |
| 120 | |
| ... |
Suppose we also have a string literal in the C function, for example from something like this:
s = "Hi Fred";
This means that the string "Hi Fred" is also somewhere in
memory, and that the value of s is the address of the
first byte in the string. We could pretend that the compiler puts the
string in memory starting at address 116. Note that the value of s is
now set to 116, which means memory location 104 hold the number 116.
We could also assign a value to i, for example:
i=22;. The picture below now represents that state of the
effected memory locations:
| 100 | |
| 104 | value of s: 116 |
| 108 | |
| 112 | value of i: 22 |
| 116 | Hi F |
| 120 | red\0 |
| ... |
Now keep in mind the following examples of how various C expressions relate to the picture above:
|
Want more? OK - add this to the picture:
char **p = &s;
Now p is a variable that holds in it the address of
s. Let's assume p is placed in memory at address 100:
| 100 | value of p: 104 |
| 104 | value of s: 116 |
| 108 | |
| 112 | value of i: 22 |
| 116 | Hi F |
| 120 | red\0 |
| ... |
|