Nodle’s Notes:

Hi just a preface here. There’s going to be a lot of hand copying the code you see here into your editor. This is for you to get used to hand writing code from scratch for the time being. In the later labs we’ll start letting you download code files to save time and prevent tedium but we thought at least for a lab it’s important to get a feel for writing code from scratch since beyond labs and exams you will be doing a lot of that.

Getting Started

Please use CS1010 WebTop for your labs and volumes, not Tutorial environments!

You should use CS1010 WebTop as the main environment for everything except graded tutorial exercises. Your files are always saved on a WebTop, whereas they would be cleared if you stopped a Tutorial environment.

Activity 1: Hello World

We’re going to start off by having you compile (via clang) your very first program.

#include <stdio.h>
 
int main(){
	printf("Hello world!\n");
	return 0;
}

Part 1:

Open up an editor and put this code in a file named hello.c. Save it, and verify that indeed the file exists with the required contents after saving (you can use ls to list files in the directory and cat hello.c to show its contents).

Then, run clang -o hello hello.c. Run ls again to see that there should be another file now called hello (without the .c suffix). This file is the program, or rather, we often prefer the term executable.

Next, run the command ./hello and observe what happens on the terminal. If all goes as expected, you should see the text Hello world!.

Part 2:

Reopen the file, and remove the \n from the printf statement. Then recompile and rerun the program. What has changed? Can you observe any notable differences? What do you think the \n does?

Play around with the text within the print statement. Add the \n back in. In fact, add a few if you want. What about interspersing the \n between some characters? Recompile and run each time. Check and see if the output matches your expectations.

Add a few of your own printf statements. Customise the message you wish to make.

The goal here is to get you used to the flow of writing code, compiling, running, and looking at the output to see if it matches your expectations. Get used to it, we (especially you) will be doing this very often!

Part 3:

Delete the hello executable before continuing (remember the rm command?)

Now reopen the file, and remove the #include <stdio.h> line. Try to recompile just like before. A few questions:

  1. Is there still a hello executable? Does it exist?
  2. In the process of trying to compile hello.c did you get any messages? Are they warnings, or are they errors?
  3. If there are any warnings/errors, try to figure out what it’s trying to say

Part 4:

Delete the hello executable before continuing (remember the rm command?)

Add the #include <stdio.h> back in and remove the semicolon from the printf statement.

Try to recompile just like before. A few questions:

  1. Is there still a hello executable? Does it exist?
  2. In the process of trying to compile hello.c did you get any messages? Are they warnings, or are they errors?
  3. If there are any warnings/errors, try to figure out what it’s trying to say

Part 5:

Delete the hello executable before continuing (remember the rm command?)

Add the semicolon back in, and remove the return 0; statement.

Try to recompile just like before. A few questions:

  1. Is there still a hello executable? Does it exist?
  2. In the process of trying to compile hello.c did you get any messages? Are they warnings, or are they errors?
  3. If there are any warnings/errors, try to figure out what it’s trying to say

Activity 2: Division

Next, we’re going to start printing values. Go ahead and create a file for code called divide.c. In it, fill out the following code:

#include <stdio.h>
 
int main(){
	double a, b;
	a = 1;
	b = 3;
	printf("%f\n", a / b);
	return 0;
}

Part 1

Compile by running clang -o divide divide.c (note the change in name!) and run it using ./divide. Is the output as expected? What do you see?

Part 2

Add a few print statements that also print the values of a and b themselves. Then compile and run again to confirm that the changes in your code worked.

Part 3

Change the code so that variable b is initialised to the value 0.

  1. Compile by running clang -o divide divide.c
  2. Did it compile? Were there errors? If so, what were the errors?
  3. If it successfully compiled, were there warnings? If so, what were the warnings?
  4. If it successfully compiled, you should now have a new divide executable. Try running it again via ./divide
  5. What does it print? If you had placed your print statements in part 2 before the given print statement, do they also print? Do they not print?

Activity 3: Overflow and Integer Sizes

We are now going to explore the sizes of the different integer types. Go ahead and open up a file called sizes.c and type in the following code:

#include <stdio.h>
#include <stdint.h>
 
int main(){
	uint8_t a = 0;
	printf("%d\n", a + 1);
	printf("%d\n", a++);
	printf("%d\n", a);
	return 0;
}

Part 0:

Run it, and try to explain the behaviour / reason behind the program as best you can. In particular, what do you think the a++ is doing?

Part 1:

Change the a++ from the second print statement into ++a. Compile it and run it again. Now try to explain the behaviour. What do you think the ++a is doing?

Part 2:

Now change the initialisation of variable a to 255 (instead of 0). Compile it and run it again. Now try to explain the behaviour now.

It might be helpful to know that uint8_t should be parsed as: “8 bit unsigned integer type”.

Part 3:

Change the type of variable a to uint16_t. Recompile and rerun the program again. How has the behaviour changed now? What is the reason behind the change?

Part 4:

Change the type of variable a to int8_t (note that we originally started with uint8_t). Recompile and rerun the program now. What differences do you note?

Part 5:

Based on these behaviours, what do you think the maximum and minimum possible values are for variables of type uint8_t and int8_t respectively?

Part 6:

Extrapolate your guesses for variables of type uint16_t and int16_t. Come up with programs that verify your guesses. Compile them and run them to see if you were right.

Activity 4: ASCII and man Pages

Make a file for your code called char.c. In it, write the following code:

#include <stdio.h>
 
int main(){
	char a = 'h';
	printf("%c\n", a);
	return 0;
}

Part 1

Compile and run it. Does the output match your expectations?

Part 2

Change the %c in your print statement to %d. Recompile, and run it now. Has the output changed? If so, what is the difference?

Part 3

In the terminal, run man ascii. You should be greeted with a page that you can scroll up and down with arrow keys. Scroll down and look at the table. Particularly on the column char. This is where all the possible ASCII characters are listed.

Look for the row that corresponds to char and look for the h character. What decimal value does it have? (Refer to the column likely titled Dec.)

Based on that information, what can you say about using %c vs %d in your printf statement for characters?

Part 4

Change the %d in your printf statement to %x. Recompile, and run it again. You should have new output. Refer to the table again. Based on what you see, make an educated guess about what %x is trying to print.

Part 5

Without running the following code, predict the behaviour of what it will print.

#include <stdio.h>
 
int main(){
	printf("%c\n", 67);
	return 0;
}

You may refer to the ASCII table by running man ascii again.

Activity 5: More about ints vs floating point values

#include <stdio.h>
 
int main(){
	int x = 888;
	printf("%d\n", x * 9 / 100);
	printf("%d\n", x * 0.09);
	return 0;
}

Part 1:

Compile the following code above. Look at the lines being output by the program and try to explain any discrepancies you might have noticed.

Part 2:

Add the following lines into the program:

	printf("%f\n", x * 9 / 100);
	printf("%f\n", x * 0.09);

Compile and look at the output again. Based on the program output, can you try explaining the outputs now?

Part 3:

Based on the previous parts, what can you say about x * 9 / 100 vs x * 0.09?

Activity 6: Integer Literals and Types

#include <stdio.h>
 
int main(){
	int x = 2147483647 + 1;
	printf("%d\n", x);
	printf("%ld\n", x);
 
	unsigned long y = 2147483647 + 1;
	printf("%d\n", y);
	printf("%ld\n", y);
 
	unsigned long z = 2147483647ul + 1;
	printf("%d\n", z);
	printf("%ld\n", z);
}

Part 1:

Compile the above code and try to spot any warnings. You don’t have to fix them. But try to explain why each warning has shown up.

Part 2:

Note the differences between how variables x, y, and z were declared and initialized. Try to explain the discrepancies between the outputs. Pay special attention to the fact that z has an additional ul at the end of the number.