/* This is the handout for lecture 17, which is a revision * lecture, mostly on the subject of pointers. */ /* The code below is written in such a way as to allow us to * program to experiment with the behaviour of pointers. */ /* First thing to remember is the following: * A pointer variable is a variable which stores memory * addresses (ie stores the LOCATION of a variable of * the specified type in memory). */ /* It is possible to print out the memory address of a pointer * to the screen (appears in Hexadecimal format). We are * going to do this. */ /* We have a few issues to consider in this lecture. */ /* The first issue we will consider is the effect of using * pointers in the call-by-value environment. Although pointers * are also passed on a call-by-value basis, the value passed * (when we are passing a pointer) is the address of a location * in memory. In this scenario "call-by-value" means that the * address is copied-by-value (hence the original pointer cannot * be re-assigned). However, since we have a direct copy of the * address of this location, we are able to chnage WHAT IS STORED * at that location (of course making sure we have the right type)!!! * This might sound like a contradiction to "call-by-value", but * it is not so. The pointer itself DID get passed on a value * basis. And if we were to give the pointer a new value * (ie, a new memory location) inside our function, that would * NOT change the pointer variable in 'main'. */ /* Second issue we will consider is the relationship between * pointers (of a particular type) and arrays (of the same type). * They are similar in many ways (the name of an array IS a * pointer to a location of the specified type. However, * an array is a STATIC pointer, meaning that we cannot change * the location that pointer points to. More details below. */ #include #include /* We are going to use the function below to get a detailed * understanding of what happens during parameter-passing * to a function, and within that function. When calling this * function from 'main', two arguments will be passed * - some variable/value which is a memory location storing an int, * - also some integer value (either value or int variable). * Both those will be "passed-by-value", meaning that after * the call, the compiler will create the local variables 'a' * and 'b' for 'changeValues' and COPY OVER the values of the * passed arguments into these new variables. */ /* 'a' is a (local) pointer variable which points to type int. * 'b' is a (local) integer variable. */ int changeValues(int *a, int b) { printf("--------------------------------------------------\n"); printf("Inside the 'changeValues' function:\n\n"); printf("Pointer variable 'a' has value %p and points to %d.\n", a, *a); printf("Integer variable 'b' has value %d and is stored at %p.\n", b, &b); printf("\n"); *a = *a +5; b = b+5; printf("After the updates, 'a' has value %p and points to %d.\n", a, *a); printf("After the updates, 'b' has value %d and is stored at %p.\n", b, &b); printf("Leaving the 'changeValues' function.\n"); printf("--------------------------------------------------\n"); return EXIT_SUCCESS; } int main(void) { /* int a[] = {2, 3, 5, 7, 9, 11, 13, 14, 16, 19}; */ int x, y, z; char c; int *p, *q; /* p, q are pointers to variables of type int. */ p = &x; /* We set p to 'point to variable x'. This can */ /* also be read as 'give p the address of x'. */ x = 17; y=13; z = 5; q = &x; /* ALSO give q the address of x. */ /* We can test whether pointers are the same, just like other * variables. This means we are asking whether they point * to the same address. In the test below, == should definitely * return true. */ if (p == q) printf("p and q point to the same address. This is %p.\n", p); else printf("Something weird is going on with p, q!!\n"); /* Apart from testing pointers to see they are the same, we * can also just print out their values (as seen above). * Let's see the various addresses of x, y, z. They will * probably be close to each other in memory (and therefore * the Hex will be close) because they were declared as a * group. */ printf("Want to see some pointer addresses? 'y' OR 'n'\n"); scanf("%c", &c); if (c=='y' || c=='Y') { printf("\n"); printf("The address of 'x' is %p.\n", &x); printf("The address of 'y' is %p.\n", &y); printf("The address of 'z' is %p.\n", &z); printf("\n"); printf("Notice (of course) that the address of 'x' is 'p'.\n\n"); } printf("Now I will show details of parameter-passing?\n\n"); printf("We experiment with 'changeValues'(int *a, int ).\n"); printf("We will pass in the pointer variable 'p' and the value 'z'\n"); printf("Parameter 'p' has value %p, points to %d.\n", p, *p); printf("Parameter 'z' has value %d, stored at %p.\n", z, &z); printf("Now we will call 'changeValues(p,z)'\n\n"); sleep(80); changeValues(p,z); sleep(80); printf("\n We saw what happened *inside* the 'changeValues' call.\n"); printf("Now let's see what has happened to p, z afterwards.\n\n"); sleep(80); printf("Parameter 'p' now has value %p, points to %d.\n", p, *p); printf("Parameter 'z' now has value %d, stored at %p.\n\n", z, &z); printf("Neither address or value of z has changed.\n"); printf("But the value pointed to by p should have changed.\n"); return EXIT_SUCCESS; }