Week 01 Tutorial Answers

  1. Class introduction (for everyone, starting with the tutor):

    • Please turn on your camera for the introduction, and for all your COMP1521 tut-labs,
      if you can and you are comfortable with this.
      We understand everyone can be having a difficult day, week or year so
      having your webcam on is optional in online COMP1521 tut-labs,
      unless you have a cute pet in which case it's required, but you only need show the pet.
    • What is your preferred name (what should we call you?)
    • What other courses are you doing this term
    • What parts of C from COMP1511/COMP1911 were the hardest to understand?
    • Do you know any good resources to help students who have forgotten their C? For example:
  2. Consider the following C program skeleton:
    int  a;
    char b[100];
    
    int fun1() {
        int c, d;
        ...
    }
    
    double e;
    
    int fun2() {
        int f;
        static int ff;
        ...
        fun1();
        ...
    }
    
    int g;
    
    int main(void) {
        char h[10];
        int i;
        ...
        fun2()
        ...
    }
    

    Now consider what happens during the execution of this program and answer the following:

    1. Which variables are accessible from within main()?

    2. Which variables are accessible from within fun2()?

    3. Which variables are accessible from within fun1()?

    4. Which variables are removed when fun1() returns?

    5. Which variables are removed when fun2() returns?

    6. How long does the variable f exist during program execution?

    7. How long does the variable g exist during program execution?

  3. Explain the differences between the properties of the variables s1 and s2 in the following program fragment:
    #include <stdio.h>
    
    char *s1 = "abc";
    
    int main(void) {
        char *s2 = "def";
        // ...
    }
    

    Where is each variable located in memory? Where are the strings located?

  4. C's sizeof operator is a prefix unary operator (precedes its 1 operand) - what are examples of other C unary operators?
  5. Why is C's sizeof operator different to other C unary & binary operators?
  6. Discuss errors in this code:
        struct node *a = NULL:
        struct node *b = malloc(sizeof b);
        struct node *c = malloc(sizeof struct node);
        struct node *d = malloc(8);
        c = a;
        d.data = 42;
        c->data = 42;
    
  7. What is a pointer? How do pointers relate to other variables?
  8. Consider the following small C program:

    #include <stdio.h>
    
    int main(void) {
        int n[4] = { 42, 23, 11, 7 };
        int *p;
    
        p = &n[0];
        printf("%p\n", p); // prints 0x7fff00000000
        printf("%lu\n", sizeof (int)); // prints 4
    
        // what do these statements print ?
        n[0]++;
        printf("%d\n", *p);
        p++;
        printf("%p\n", p);
        printf("%d\n", *p);
    
        return 0;
    }
    

    Assume the variable n has address 0x7fff00000000.

    Assume sizeof (int) == 4.

    What does the program print?

  9. Consider the following pair of variables

    int  x;  // a variable located at address 1000 with initial value 0
    int *p;  // a variable located at address 2000 with initial value 0
    

    If each of the following statements is executed in turn, starting from the above state, show the value of both variables after each statement:

    1. p = &x;

    2. x = 5;

    3. *p = 3;

    4. x = (int)p;

    5. x = (int)&p;

    6. p = NULL;

    7. *p = 1;

    If any of the statements would trigger an error, state what the error would be.

  10. Consider the following C program:

    #include <stdio.h>
    
    int main(void)
    {
        int nums[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
        for (int i = 0; i < 10; i++) {
            printf("%d\n", nums[i]);
        }
        return 0;
    }
    

    This program uses a for loop to print each element in the array

    Rewrite this program using a recursive function

  11. What is a struct? What are the differences between structs and arrays?
  12. Define a struct that might store information about a pet.

    The information should include the pet's name, type of animal, age and weight.

    Create a variable of this type and assign information to it to represent an axolotl named "Fluffy" of age 7 that weighs 300grams.

  13. Write a function that increases the age of fluffy by one and then increases its weight by the fraction of its age that has increased. The function is defined like this:

    void age_fluffy(struct pet *my_pet);

    e.g.: If fluffy goes from age 7 to age 8, it should end up weighing 8/7 times the amount it weighed before. You can store the weight as an int and ignore any fractions.

    Show how this function can be called by passing the address of a struct variable to the function.

  14. Write a main function that takes command line input that fills out the fields of the pet struct. Remember that command line arguments are given to our main function as an array of strings, which means we'll need something to convert strings to numbers.
  15. Consider the following C program:
    #include <stdio.h>
    
    int main(void) {
        char str[10];
        str[0] = 'H';
        str[1] = 'i';
        printf("%s", str);
        return 0;
    }
    
    What will happen when the above program is compiled and executed?
  16. How do you correct the program.
  17. For each of the following commands, describe what kind of output would be produced:

    1. gcc -E x.c
    2. gcc -S x.c
    3. gcc -c x.c
    4. gcc x.c

    Use the following simple C code as an example:

    #include <stdio.h>
    #define N 10
    
    int main(void) {
        char str[N] = { 'H', 'i', '\0' };
        printf("%s\n", str);
        return 0;
    }
    
  18. Consider the following (working) C code to trim whitespace from both ends of a string:

    // COMP1521 21T2 GDB debugging example
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <assert.h>
    
    void trim(char *str);
    char **tokenise(char *str, char *sep);
    void freeTokens(char **toks);
    
    int main(int argc, char **argv)
    {
    	if (argc != 2) exit(1);
    
    	char *string = strdup(argv[1]);
    	printf("Input: \"%s\"\n", string);
    	trim(string);
    	printf("Trimmed: \"%s\"\n", string);
    	char **tokens = tokenise(string, " ");
    	for (int i = 0; tokens[i] != NULL; i++)
    		printf("tok[%d] = \"%s\"\n", i, tokens[i]);
    	freeTokens(tokens);
    	return 0;
    }
    
    // trim: remove leading/trailing spaces from a string
    void trim(char *str)
    {
    	int first, last;
    	first = 0;
    	while (isspace(str[first])) first++;
    	last  = strlen(str)-1;
    	while (isspace(str[last])) last--;
    	int i, j = 0;
    	for (i = first; i <= last; i++) str[j++] = str[i];
    	str[j] = '\0';
    }
    
    // tokenise: split a string around a set of separators
    // create an array of separate strings
    // final array element contains NULL
    char **tokenise(char *str, char *sep)
    {
    	// temp copy of string, because strtok() mangles it
    	char *tmp;
    	// count tokens
    	tmp = strdup(str);
    	int n = 0;
    	strtok(tmp, sep); n++;
    	while (strtok(NULL, sep) != NULL) n++;
    	free(tmp);
    	// allocate array for argv strings
    	char **strings = malloc((n+1)*sizeof(char *));
    	assert(strings != NULL);
    	// now tokenise and fill array
    	tmp = strdup(str);
    	char *next; int i = 0;
    	next = strtok(tmp, sep);
    	strings[i++] = strdup(next);
    	while ((next = strtok(NULL,sep)) != NULL) strings[i++] = strdup(next);
    	strings[i] = NULL;
    	free(tmp);
    	return strings;
    }
    
    // freeTokens: free memory associated with array of tokens
    void freeTokens(char **toks)
    {
    	for (int i = 0; toks[i] != NULL; i++) free(toks[i]);
    	free(toks);
    }
    

    You can grab a copy of this code as trim.c.

    The part that you are required to write (i.e., would not be part of the supplied code) is highlighted in the code.

    Change the code to make it incorrect. Run the code, to see what errors it produces, using this command:

    gcc -std=gnu99 -Wall -Werror -g -o trim trim.c
    ./trim  "   a string  "
    

    Then use GDB to identify the location where the code "goes wrong".

Revision questions

The following questions are primarily intended for revision, either this week or later in session.
Your tutor may still choose to cover some of these questions, time permitting.