#include <stdio.h>
#include <stdlib.h>
/* Line 1 */ int *a(int *b, int **c)
/* Line 2 */ {
/* Line 3 */ int *j;
/* Line 4 */
/* Line 5 */ *c = (*c)+1;
/* Line 6 */ **c = 25;
/* Line 7 */ printf("0x%x 0x%x 0x%x 0x%x\n", b, *b, c, *c);
/* Line 8 */
/* Line 9 */ j = (int *) malloc(sizeof(int) * (b[0] + b[1]));
/* Line 10 */
/* Line 11 */ return j;
/* Line 12 */ }
/* Line 13 */
/* Line 14 */ int main()
/* Line 15 */ {
/* Line 16 */ int b[40];
/* Line 17 */ int i;
/* Line 18 */ int **c;
/* Line 19 */ int *d;
/* Line 20 */ int *j;
/* Line 21 */
/* Line 22 */ d = b;
/* Line 23 */
/* Line 24 */ for (i = 0; i < 40; i++) b[i] = 10*(i+1);
/* Line 25 */
/* Line 26 */ c = &d;
/* Line 27 */
/* Line 28 */ printf("0x%x 0x%x 0x%x 0x%x\n", b, &c, &d, &j);
/* Line 29 */
/* Line 30 */ j = a(b, c);
/* Line 31 */
/* Line 32 */ printf("0x%x 0x%x\n", j, d);
/* Line 33 */ exit(0);
/* Line 34 */ }
|
Suppose the first line of output is the following:
0xbffff01c 0xbffff0bc 0xbffff0c0 0xbffff0c4 |
Variable c resides at memory location 0xbffff0bc, and d resides at memory location 0xbffff0c0. Finally, j resides at memory location 0xbffff0c4. Since d = b, we know d's value is 0xbffff01c. And since c = &d, we know c's value is 0xbffff0c4. We don't know j's value, since it is uninitialized. Here is the picture of memory just before a() is called:
|
Now, when we call a() three more memory locations are allocated -- four bytes for parameter b, four bytes for parameter c, and four bytes for local variable j. Since we never print out their addresses, I will put question marks for them, but they are drawn below in violet. You'll note, we know the values of b and c, since they are copied from b and c in the main() program:
|
Now, we do "*c = *(c) + 1". Since c is 0xbffff0c0, the value that is in that memory location (this is d in main()) is incremented by four. It is incremented by four rather than one since we are doing pointer arithmetic. This is shown below:
|
Next, we do "**c = 25". C is 0xbffff0c0, so *c is what resides at memory location 0xbffff0c0. This means that *c is 0xbffff020. This means that **c is what is located at memory location 0xbffff020 (which is b[1]). This gets changed to 25 in the picture below:
|
We now print out b, *b, c, and *c. Use the picture to figure that out: 0xbffff01c, 0xa (ten in hexadecimal), 0xbffff0c0, and 0xbffff020.
Now, we do the malloc(), which will allocate 35 integers. We don't know what it returns, but it does return a new memory address. I picture that below:
|
Finally, a() returns. You note, the violet memory locations go away, since they were part of a(), and the newly allocated memory gets returned to j. Again, we don't know what j is, but it is a pointer to the memory returned by malloc().
|
The final printf() statement will printout j's value (the something in the picture), and then d's value, which is 0xbffff020. Note, one effect of procedure a() was to change d's value. This may seem confusing, but that's life with pointers. Here's the output of the program:
0xbfffef9c 0xbffff03c 0xbffff040 0xbffff044 0xbfffef9c 0xa 0xbffff040 0xbfffefa0 0x500160 0xbfffefa0 |
0xbffb5e00 0xbffb5df8 0xbffb5df4 0xbffb5df0 0xbffb5e00 0xa 0xbffb5df4 0xbffb5e04 0x81cd008 0xbffb5e04 |
You should note that while the numbers of the memory locations are different, their interrelationships are the same.
int *a(int *b, int **c)
{
int *j;
int i;
for (i = 0; i < 400; i++) b[i] = i*7;
*c = (*c)+1;
**c = 25;
printf("0x%x 0x%x 0x%x 0x%x\n", b, *b, c, *c);
j = (int *) malloc(sizeof(int) * (b[0] + b[1]));
return j;
}
|
You'll note that the for loop stomps over more memory than just b -- it stomps on c, d, etc:
|
The "*c = (*c) + 1" adds four to the value in memory location 0xbffff0c0 -- changing 287 to 291:
|
However, you do get a bus error at the "**c = 25" line. This is because c is 0xbffff0c0, and the value at that address is 291. Therefore *c = 291, and when the computer tries to set the memory at location 291, it gets a bus error, since 291 is not a multiple of 4:
|