‼️

Quiz 4

TypeAssessment
  1. In C, #include statements are expanded during the ?? step of the compilation process
    • Answer

      preprocessing

  1. Write a macro called FUN_DIVIDE that divides numbers A and B then adds 9 to the result. Make sure the result is a floating-point number.
    • Answer

      #define FUN_DIVIDE((a), (b)) (((a) / (b)) + 9.0)

      Necessary to include parenthesis around each 'parameter' (recall macro perils).

  1. In one of Jack's files called foo1.c, he declares and defines a global static double called PI and a function main() like so:
    #include "foo1.h"
    
    	static double PI = 3.1415;
    	
    	int void main() {
    	
    		printf("Hello Quiz 4");
    
    	}

    Is this valid? Why or why not?

    • Answer

      INVALID

      main() is a function defined to have a return type of both int AND void, which is invalid

  1. Consider the following code and determine where the following items are stored in memory. Then, determine the result of this program.
    #include <stdio.h>
    	int *getNthElement(int n) {
    		static int nums[] = {48, 45, 69, 02, 12, 61, 04, 58, 42, 82};
    		char letter = 'U';
    		int myNum = nums[n];
    		return &myNum;
    	}
    	
    	int count = 8348;
    
    	int main(void) {
    		int *x = getNthElement(6);
    		printf("%d\n", *x);
    		return 0;
    	}

    getNthElement

    nums

    count

    x

    n

    • Answer

      getNthElement: data segment

      nums: data segment

      count: data segment

      x: stack

      n: stack

  1. Type the corresponding C declaration that matches the description given for each part

    a) b is a pointer to a pointer to a long

    b) f is a pointer to a function that takes in a pointer to an int and returns a pointer to a pointer to a char

    c) junk is a pointer to a function that takes in no parameters and returns a pointer to a pointer to a struct trash

    d) h is an array of size 2110 that contains pointers to pointers to struct students

    • Answer
      1. long **b
      1. char **(*f)(*int);
      1. struct trash **(*junk)(void)
      1. struct student **h[2110]
  1. Consider the following code and determine what the program will print. Then, use the dropdown to determine which arguments are pass by reference.
    #include <stdio.h>
    
    void func(int a, int *b, int *c) {
    	a++;
    	c = b;
    	*b = a + 7;
    	(*c)++;
    }
    
    void main(void) {
    	int a = 12;
    	int b = 9;
    	int c = 36;
    	func(a, &b, &c);
    	printf("a: %d\n", a);
    	printf("b: %d\n", b);
    	printf("c: %d\n", c);
    }

    a:

    b:

    c:

    Which of the arguments are passed by reference?

    • Answer:

      a: 12

      b: 21 ( 12 + 7 + 1)

      c: 36

      Which of the arguments are passed by reference? None

  1. Will the following code run without error? If yes, what is the output? If not, explain the error and why it failed.
    #include <stdio.h>
    
    char * returnSomeLetters(char *str) {
    	char result[4];
    	for (int i = 0; i < 3; i++) {
    		result[i] = str[i];
    	}
    	result[3] = '\0';
    	return result;
    }
    
    int main() {
    	char string[] = "cs2110 is my favorite class";
    	char *result = returnSomeLetters(string);
    	printf("%s", result);
    }
    • Answer

      The code fails. The result is declared on the stack since it exists inside the function. When it is returned, the address of the result cannot be found since the stack is reset, and the pointer to the result will go somewhere bad.

  1. Will of the following function always run correctly? If not, explain when it would fail
    struct Doggo {
    	char * name;
    	int goodBoi;
    	long numMailmenScared;
    	int isChonker;
    };
    
    int isVeryGoodBoi() {
    	if (newDoggo->isChonker) {
    		return 1;
    	}
    	if (newDoggo->numMailmenScared <= 0) {
    		return 0;
    	}
    	if (newDoggo->goodBoi) {
    		return 1;
    	} else {
    		return 0;
    	}
    }
    • Answer

      The answer is that newDoggo could be an invalid pointer such as NULL, if so, dereferencing it would cause a seg fault.

  1. Your head TA, Shawn Wahi, claims that both lines 4 and 5 in his code below are valid. Is it? If so, why? If not, where is the error and why not?

    char * OH = "By Appointment Only";

    char arr[20] = "1 to 3";

    char * temp = arr;

    arr = OH; //line 4

    OH = temp; //line 5

    • Answer

      line 4 is not valid since we cannot assign thee string OH to the array arr;

  1. Consider the code provided below. For the blank labeled [1], fill in the parameter list according to the implementation of doublePower provided in the code. For blank [2], write a single statement that will double the existing barkPower of the puppy. Assume that the structs have already been initialized with some initial values, and any parameter name may be used in blank [1], as long as it is consistent with blank [2].
    #include <stdio.h>
    #include <string.h>
    
    //stats struct
    struct stats {
    	int age;
    	double barkPower;
    	double jumpHeight;
    }
    
    //puppy struct
    struct puppy {
    	char *name;
    	struct stats puppyStats;
    }
    
    int main() {
    	struct puppy p1;
    	doublePower(&p1);
    	return 0;
    }
    
    int doublePower(//CODE HERE) {
    	//CODE HERE
    }
    • Answer
      int doublePower(struct puppy *p) {
      	p->puppyStats.barkPower = (p->puppyStats.barkPower) * 2;
      }
  1. In the table below you’ll find a representation of memory in a computer. Each memory address is capable of storing 1 byte of information. For example, if I were to retrieve 2 bytes starting at address 0x123002, I would get 0xE058.

    You may assume long is 8 bytes, an int is 4 bytes, a short is 2 bytes, and a char is 1 byte.

    int * ptr1 = (int*)(0x123013);

    short * ptr2 = (short*)(0x123008);

    long* ptr3 = (long*)(0x123000);

    Answer the following questions. Give your answer in hexadecimal.

    ptr3 = ?

    ptr3 + 1 = ?

    *(ptr1 + 2) = ?

    *(ptr2 +4) = ?

    • Answer

      ptr3 = 0x123000

      ptr3 + 1 = 0x123008

      *(ptr1 + 2) = 0xC2D4E3A1. 123013 + 2*4 = 12301B

      *(ptr2 + 4) = 0xDB8E. 123008 + 8 = 123010

  1. You will be allowed to use the following string functions:
    • strncmp
    • strncpy
    • strlen

    You can assume string.h has already been included.

    Write a function replaceCharWithString that replaces a char with string. Do NOT modify the original string. You will be given 4 arguments:

    • (char *originalString). null-terminated string to modify.
    • (char charToReplace). char you are looking to replace
    • (char *stringReplace). null-terminated string that will replace the char
    • (char *result). string to store the result. You can assume that it has been initialized with enough memory to hold the entire resulting null-terminated string.

    Example 1: replaceCharWithString("hi", 'i', "ello", res) should result in res containing the null-terminated string "hello".

    Example 2: replaceCharWithString("beautiful", 'u', "uwu", res) should result in res containing the null-terminated string "beauwutifuwul".

    Copy the following function header into the box:

    void replaceCharWithString(char * originalString, char charToReplace, char * stringReplace, char *result)
    • Answer
      void replaceCharWithString(char *originalString, char charToReplace, char *stringReplace, char *result) {
          const int replaceLen = strlen(stringReplace);
          while (*originalString) { // until we reach a null terminator
              if (*originalString == charToReplace) {
                  strncpy(result, stringReplace, replaceLen); // copy all replacement chars except the null terminator
                  result += replaceLen;
              } else {
                  *result = *originalString; // copy the current character
                  result++;
              }
              originalString++; // look at the next character
          }
          *result = '\0'; // ensure the result is null-terminated
      }