Skip to main content

Dive Into Systems: Exercises

Section 2.3 Pointers and Functions

Checkpoint 2.3.1. Pointers.

Consider the following snippet of code:
int x, y, *z;

x = 1;
y = x * 2;
z = &x;
x = y * 2;
List the values of the following expressions after executing the statements above.
x is
y is
*z is
Hint.
Draw pictures of variables and their values as you trace through the execution of each statement.

Checkpoint 2.3.2. Pass by Reference vs Pass by Value (Q1).

    Consider the following code snippet:
    int mystery(int y) {
        y = 6;
        return y*y;
    }
    
    int main(void) {
        int x, *ptr;
    
        ptr = &x;
        x = 34;
        ret = mystery(x);
    }
    
  • 34
  • Correct! The value of x in the main function remains unchanged.
  • 36
  • Incorrect. That is the value of ret not x!
  • 6
  • Incorrect. Trace through the program carefully again.
  • None of the above
  • Incorrect. It is one of the options above!

Checkpoint 2.3.3. Pass by Reference vs Pass by Value (Q2).

    Consider the following code snippet:
    int mystery2(int *p) {
     	    *p = 13;
        return *p + 6;
    }
    
    int main(void) {
        int x, *ptr;
    
        ptr = &x;
        x = 34;
        ret = mystery2(ptr);
    }
    
  • 19
  • Correct! Since p is a pointer to x, it modifies the value of x in the main function.
  • 13
  • Close, but incorrect! Read through the code carefully. Did you capture all options?
  • 6
  • Incorrect. Trace through the program carefully again.
  • None of the above
  • Incorrect. It is one of the options above!

Checkpoint 2.3.4. Multiple-Choice.

    Consider the following code.
    #include <stdio.h>
    
    int change_string(char *a, char *b);
    
    int main(void) {
        char alpha, beta;
    
        alpha = 'a';
        beta = 'b';
        
        change_string(&alpha, &beta);
        printf("alpha: %c beta: %c\n", alpha, beta);
    
        return 0;
    }
    
    int change_string(char *a, char *b) {
        b = a;
        // draw the stack here
        return 0;
    }
    
    PART A: What is printed when the code is compiled and run?
    PART B: Draw the stack as it appears immediately before change_string returns (at the "// draw the stack here" point). Answer appears in the "Answer" box below.
  • alpha: a; beta: a
  • Try again: If get stuck, take a look at the hint!
  • alpha: a; beta: b
  • Great work!
  • alpha: b; beta: a
  • Try again: If get stuck, take a look at the hint!
  • alpha: b; beta: b
  • Try again: If get stuck, take a look at the hint!
Hint.
Compare the code in this problem and how we change value by pointer.
Answer.
A stack drawing is shown below. Initially, variables a and b in the change_string function contain the addresses of alpha and beta respectively. When the statement b = a executes in the change_string function, b is updated to contain the address of of alpha. However, this pointer reassignment does not actually update either the values of alpha or beta. Therefore, the values in the main function remain unchanged.

Checkpoint 2.3.5. Functions calling functions, pointers.

Complete the call to calculate in main.
#include <stdio.h>

/* sums two numbers */
int compute_sum(int x, int y) {
    return x + y;
}

/*multiplies two numbers*/
int compute_product(int x, int y) {
    return x * y;
}

/* Function to perform calculations on a and b and set the
   parameters to their results */
void  calculate(int x, int y, int *sum_result, int *product_result) {
    *sum_result = compute_sum(x, b);
    *prod_result = compute_product(a, b);
}

int main(void) {

    int a = 3, b = 4;
    int sum, product;
    
    calculate(); //modify this line!
    printf("sum of %d and %d is %d \n", a, b, sum);
    printf("product of %d and %d is %d \n", a, b, product);    
    return 0;
}
Answer.
calculate(a, b, &sumResult);

Checkpoint 2.3.6. Activecode.

Implement the function swap below that attempts to swap the value of two character pointers. If either character pointer is NULL, the function should return 1. Otherwise, a and b should be swapped and the function should return 0.
Final answer below should be:
alpha: b beta: a
The retun value is: 0
       #include <stdio.h>

       int swap(char *a, char *b);

int main(void) {
    char alpha, beta;
    int ret;

    alpha = 'a';
    beta = 'b';
    
    ret = swap(&alpha, &beta);
    printf("alpha: %c beta: %c \n", alpha, beta);
    printf(“The return value is: %d\n”, ret);

    return 0;
}

/* swaps values pointed to by a and b. Returns 0 on success, 1 on error. 
 */
int swap(char *a, char *b) {
   //write code here


    return 0;
}
Hint.
In order to change the values stored at a and b, we must dereference a and b inside of swap.

Checkpoint 2.3.7. Explore a larger program.

#include <stdio.h>

int arg_modifier(int x, int *y);

int main() {
    int val1, val2, ret;

    printf("Enter a value: ");
    scanf("%d", &val1);
    printf("Enter another value: ");
    scanf("%d", &val2);

    // pass val1 by value and val2 by pointer:
    printf("before call: val1 = %d val2 = %d\n", val1, val2);
    ret = arg_modifier(val1, &val2);
    printf("after call:  val1 = %d val2 = %d ret = %d\n", val1, val2, ret);

    /*
     * uncomment to test passing val2 by value and val1 by pointer
     */
    //printf("before 2nd call: val1 = %d val2 = %d\n", val1, val2);
    //ret = arg_modifier(val2, &val1);
    //printf("after 2nd call: val1 = %d val2 = %d\n", val1, val2);

    return 0;
}

/*
 * This function illustrates C-style pass by pointer semantics, the
 * argument pointed to by the second parameter, y, will be modified
 * after the call, the value of the first argument, x, will not.
 */
int arg_modifier(int x, int *y) {

    printf("  in arg_modifier:      x = %d *y = %d\n", x, *y);

    /* the location y points to gets (value of what y points to + x) */
    *y = *y + x;

    x = x + 5;

    printf("  leaving arg_modifier: x = %d *y = %d\n", x, *y);

    return x;
}

(a)

Copy this program (ex_passbypointer.c), compile and run it a few times to understand its behavior and the semantics of pass-by-pointer. You can uncomment the second call in main that passes the local variables in different order as arguments to the function.
Hint.
Here’s the output from an example run:
Enter a value: 100
Enter another value: 200
before call: val1 = 100 val2 = 200
  in arg_modifier:      x = 100 *y = 200
  leaving arg_modifier: x = 105 *y = 300
after call:  val1 = 100 val2 = 300 ret = 105

(b)

Draw the stack for a call to the arg_modifier function, entering the values 5 and 2. Draw the stack at the point in the execution right before the return from the arg_modifier function, and consider the following questions:
  1. Where are variables val1 and val2 located on the stack?
  2. Where are the parameter values located?
  3. What value does each parameter get?
  4. How does the value of the parameter affect the value of each argument after the call?
Answer.
Here is a snapshot of the stack before arg_modifier returns. Parameter y receives the value of the address of val2 (y points to val2). By dereferencing y, it accesses the value stored in val2 --  the statement *y = *y + x; changes the value pointed to by y from 2 to 7.
  1. val1 and val2 are located in main’s stack frame
  2. in arg_modifier’s stack frame
  3. y gets the value of the second argument (the address of val2), x gets the value of the first argument (the int value stored in val1)
  4. the value of the first argument cannot be modified by the function. the value of the second argument can be modified by the function by dereferencing the pointer parameter.
diveintosystems.org/book/C2-C_depth/_attachments/ex_passbypointer.c