Contents
Lab 0: C Warmup 1
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Development Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Acquiring the code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Compiling and running the code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Submitting the exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Lab 0: C Warmup
Overview
The purpose of this assignment is to gain some basic experience with C programming, including such topics
as arrays, stack allocation, heap allocation, function calls, and memory safety (or the lack thereof). It is a
credit/no credit exercise and should take a short time to finish.
Development Environment
Since we want to make sure that all students have a working (and generally equivalent) development
environment, we are providing a Virtual Machine (VM) to use. Your first task, before starting any programming
assignment, will be to ensure that your VM is setup correctly as outlined by the instructions page. The VM
we give you will be the only officially supported environment for all programming assignments
and will be used throughout the course.
Acquiring the code
Once your VM has been properly setup, you will now be able to retrieve the provided code for this assignment.
To do so, you will have to use the update-course script located on the course VM. This script may be run
from a command-line terminal or by using the launcher located on the top toolbar or by using the launcher on
the desktop. This script will place all necessary files in the “course-materials” sub-directory within your home
folder. For convenience, a shortcut to this directory has been placed on the desktop. It is important to
our infrastructure that you do not move/rename any files in the “course-materials” directory.
Also, you should not change any files in this directory except for those that we note. You may,
however, copy files until your heart’s content.
Now that you have acquired the source file, open arrays.c in your favorite text editor. arrays.c file contains a
number of TODOs, which you are expected to complete. Most have a proceeding line that says “Answer:”,
which is where you should leave an answer to the question(s) posed in the TODO. One TODO requires you
to write some code, which you should place immediately after the comment block that describes what to do.
As a convenience, here is an archive of the course-materials directory for this lab: lab0.tar.gz.
Compiling and running the code
The source file arrays.c won’t do you any good by itself; you need a compiler (specifically the GNU C compiler)
to compile it to an executable format. The GNU C compiler is available on the VM and most popular variants
of Linux, such as Ubuntu and Fedora. You’re free to use whichever machine you like, although we will only
provide support for the VM.
Using the VM (or your own system if you’re adventurous!), open a terminal and execute gcc -v. On our
machine, here is what we see:
$ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bu gs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --prog ram-suffix=-4.6 --enable-shared --enable-linker-build-id --with-syste m-zlib --libexecdir=/usr/lib --without-included-gettext --enable-thre ads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/l ib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstd cxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --en able-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --w ith-tune=generic --enable-checking=release --build=x86_64-linux-gnu - -host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
The output tells us a bunch of the configuration options for the our installation of GCC as well as the version
number, which is 4.6.3. Navigate to the “~/course-materials/lab0” directory (where ~ denotes your home
directory) and then use GCC to compile arrays.c with the following command:
gcc -g -Wall -std=gnu99 -o arrays arrays.c
It’s not that important right now for you to know what all of these options do, but -g tells the compiler to
include debugging symbols, -Wall says to print warnings for all types of potential problems, -std=gnu99 says
to use the C99 standard (now only 14 years old!), -o arrays instructs the compiler to output the executable
code to a file called arrays, and arrays.c is the source file being compiled.
Having executed that command, you should be able to see a file named arrays in the same directory:
$ ls arrays arrays.c
The arrays file is an executable file, which you can run using ./arrays. On our machine, here is what we see:
$ ./arrays Filling an array at address 0x7fff6b4e3e60 with 10 values Done! Filling an array at address 0x7fff6b4e3eac with 1 values 2 Done! Filling an array at address 0x7fff6b4e3e90 with 4 values Done! Filling an array at address 0x11ca010 with 5 values Done!
If you look through the source code of the arrays.c file, you should be able to match up each line that is
printed with the output that you see in the console.
With that, you should have everything you need to complete the assignment. Note that every time you want
to test a modification to the source file, you will need to use the gcc -g -Wall -std=gnu99 -o arrays
arrays.c command to produce an updated arrays executable file.
Checking your work
When you have finished the exercise, please take the time to ensure that your code both compiles without
warnings (the GCC command will output lines that say “warning:” if you have warnings) and is readable. In
particular, please try to make the format of your code match that of what was given to you.
Submitting the exercise
You will be able to submit your assignment with the submit-hw script that is bundled with the lab0 course-
materials update. Using the script should be straight-forward, but it does expect you to not move/rename
any files from the “course-materials” directory. Open a terminal and type the following command:
submit-hw lab0
The script will then prompt you for your Coursera username and then your submission password. Your
submission password is NOT the same as your regular Coursera account password!!!! You may
locate your submission password at the top of the assignments list page. With a working Internet connection,
this should submit your code properly. You can go to the assignments list page to double-check that it
has been submitted and check your score as well as any feedback the auto-grader gives you. You may also
download your submission code here, if you wish.
Implementation
1 // These #includes tell the compiler to include the named 2 // header files, similar to imports in Java. The code for 3 // these is generally located under /usr/include/, such 4 // as /usr/include/assert.h. assert.h contains the 5 // declaration of the assert() function, stdio.h contains 6 // the declaration of the printf() function, and stdlib.h 7 // contains the declaration of the malloc() and free() 8 // functions, all of which are used in the code below. 9 #include10 #include 11 #include 12 13 // Fill the given array with values. Note that C doesn't 14 // keep track of the length of arrays, so we have to 15 // specify it explictly here. 16 void fillArray(int* array, int len) { 17 printf("Filling an array at address %p with %d " 18 "values\n", array, len); 19 for (int i = 0; i < len; ++i) { 20 array[i] = i * 3 + 2; 21 // assert() verifies that the given condition is true 22 // and exits the program otherwise. This is just a 23 // "sanity check" to make sure that the line of code 24 // above is doing what we intend. 25 assert(array[i] == i * 3 + 2); 26 } 27 printf("Done!\n"); 28 } 29 30 // Structs are simply storage for memory of various types. 31 // In this case, we are typedef-ing (as in naming) a 32 // struct containing four integers as FourInts. 33 typedef struct { 34 int a, b, c, d; 35 } FourInts; 36 37 // main() is the entry point of the program. 38 int main(int argc, char* argv[]) { 39 // Create a new array capable of storing 10 elements 40 // and fill it with values using the function declared 41 // above. Arrays declared in this manner are located on 42 // the stack, which is where statically allocated (as 43 // in not at runtime) memory is stored. 44 int array[10]; 45 // The "array" that we pass here is actually a pointer 46 // to a block of memory capable of storing 10 integers. 47 // array[0] is the first integer in this block of 48 // memory, array[1] is the second, and so on. Since 49 // C does not track array lengths, we have to specify 50 // how many elements the array contains. 51 // 52 // TODO(1): What happens if the second argument is set 53 // to 11 instead? How about 100? 1000? Make sure to set 54 // the second argument back to 10 when you are done 55 // testing. 56 // Answer: 57 fillArray(array, 10); 58 59 int value; 60 // In C, we can take the address of something using the 61 // & operator. &value is of the type int*, meaning that 62 // it is a pointer to an integer (as in it stores the 63 // address in memory of where the actual int is located). 64 // 65 // TODO(2): We can actually use the address of the value 66 // declared here as if it were an array of a single 67 // element; why is this possible? 68 // Answer: 69 fillArray(&value, 1); 70 // fillArray should set value to 0 * 3 + 2 = 2. 71 assert(value == 2); 72 73 // The following creates an instance of FourInts on the 74 // stack. FourInts is really just an array of four ints, 75 // although we can refer to the ints stored in it by 76 // name as well. 77 FourInts four_ints; 78 // Set the first int to have a value of 0 and verify 79 // that the value changed. 80 four_ints.a = 0; 81 assert(four_ints.a == 0); 82 83 // Depending on whether or not you like to live 84 // dangerously, the following is either exciting or 85 // terrifying. Though &four_ints is of type FourInts* 86 // (as in a pointer to a FourInts struct), we can 87 // use a cast to pretend that it is actually an array 88 // of integers instead. 89 fillArray((int*) &four_ints, 4); 90 // We can confirm that fillArray updated the values 91 // in the FourInts struct: 92 assert(four_ints.a == 2); 93 assert(four_ints.b == 5); 94 assert(four_ints.c == 8); 95 assert(four_ints.d == 11); 96 97 // In the case that the size of an array is not known 98 // until runtime, the malloc() function can be used to 99 // allocate memory dynamically. Memory that is 100 // allocated dynamically is stored on the heap, which 101 // is separate from the stack. C is unlike Java, 102 // however, in that dynamically-allocated memory must 103 // be freed explicitly when the program is done using 104 // it via the free() function. malloc() takes a single 105 // argument, which is the number of bytes to allocate. 106 // sizeof(int) gives how many bytes an int contains 107 // (which is four), so sizeof(int) * 5 is 20. 108 int* heap_array = (int*) malloc(sizeof(int) * 5); 109 fillArray(heap_array, 5); 110 // Now that we have finished with the heap-allocated 111 // array, free() the memory associated with it. 112 // 113 // TODO(3): What happens if we remove the free() 114 // statement below? Try running "valgrind ./arrays" 115 // after compiling the program both with and without 116 // it. valgrind is a tool for analyzing how programs 117 // use memory, which is often invaluable for C and 118 // C++ programming. 119 // Answer: 120 free(heap_array); 121 122 // TODO(4): Now it's your turn to write some code. 123 // Using malloc(), allocate a FourInts struct 124 // dynamically (on the heap) and use fillArray to 125 // populate it with values. Make sure to free the 126 // memory when you are done, and use the valgrind 127 // tool mentioned above to check that there aren't 128 // any errors. As a "sanity check," add four assert 129 // statements to verify that the a, b, c, and d 130 // fields of the FourInts struct are set to what 131 // you would expect. (Hint, you'll need to use the 132 // -> operator to access fields of a FourInts* 133 // variable instead of the . operator). 134 int* heap_four = (int*) malloc(sizeof(FourInts)); 135 fillArray(heap_four,4); 136 137 assert(four_ints.a == 2); 138 assert(four_ints.b == 5); 139 assert(four_ints.c == 8); 140 assert(four_ints.d == 11); 141 142 return 0; 143 }
Excecution
bash-4.2$ cd Desktop/course-materials/lab0 bash-4.2$ gcc -g -Wall -std=gnu99 -o arrays arrays.c bash-4.2$ ./arrays Filling an array at address 0x7fff58a9be50 with 10 values Done! Filling an array at address 0x7fff58a9be4c with 1 values Done! Filling an array at address 0x7fff58a9be30 with 4 values Done! Filling an array at address 0x2549010 with 5 values Done! Filling an array at address 0x2549010 with 4 values Done! bash-4.2$ valgrind ./arrays ==2221== Memcheck, a memory error detector ==2221== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==2221== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==2221== Command: ./arrays ==2221== Filling an array at address 0x7ff0005b0 with 10 values Done! Filling an array at address 0x7ff0005ac with 1 values Done! Filling an array at address 0x7ff000590 with 4 values Done! Filling an array at address 0x4c30040 with 5 values Done! Filling an array at address 0x4c300a0 with 4 values Done! ==2221== ==2221== HEAP SUMMARY: ==2221== in use at exit: 16 bytes in 1 blocks ==2221== total heap usage: 2 allocs, 1 frees, 36 bytes allocated ==2221== ==2221== LEAK SUMMARY: ==2221== definitely lost: 16 bytes in 1 blocks ==2221== indirectly lost: 0 bytes in 0 blocks ==2221== possibly lost: 0 bytes in 0 blocks ==2221== still reachable: 0 bytes in 0 blocks ==2221== suppressed: 0 bytes in 0 blocks ==2221== Rerun with --leak-check=full to see details of leaked memory ==2221== ==2221== For counts of detected and suppressed errors, rerun with: -v ==2221== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2) bash-4.2$