This page lists the code-quality guidelines used when reviewing Exercise Volumes. The guidelines apply to code you write or change.

Important

  1. This page does not define if your code for a given exercise is ‘correct’. Each exercise specifies its own required behaviour, inputs, outputs, and other correctness requirements. This page only defines general requirements for your programs.
  2. Any guideline on this page (and others that we may add) may be enforced during code review. TAs may comment on any guideline. If a TA identifies a violation, you must fix it before resubmitting, or discuss with the TA if you believe the guideline does not apply.
  3. When the guidelines apply: If a guideline mentions concepts that we haven’t covered, you can ignore it

You don't have to be perfect - we'll teach you this over time!

This might seem overwhelming at first - don’t worry! Throughout your labs, your TAs will work with you and give you comments and ideas on how to express clear code intent in your programs. This takes time!

Table of Guidelines

GuidelineSummary
G0: Compile and terminate without warningsCompile successfully without warnings and terminate on valid exercise inputs.
G1: Avoid undefined behaviourDo not execute undefined behaviour or produce sanitizer reports.
G2: Make code intent clearMake intent clear through comments, structure, and the way code is written.
G3: Use appropriate numeric typesUse int for integral values by default, unsigned int for known non-negative values, and double for values that may not be whole numbers.
G4: Use const when a value or pointee should not be modifiedUse const when a value or pointee should not be modified.
G5: Use booleans instead of integers where applicableUse booleans instead of integers when a value represents a condition.
G6: Avoid global variables where possibleKeep state local and pass it through parameters and return values unless module-wide sharing is justified.
G7: Use structured control flow instead of gotoDo not use goto; keep control-flow paths structured and visible.
G8: Don’t leak memoryDo not leak memory; free memory that your code is responsible for freeing.
G9: Read input safelyDo not use scanf; read lines with getline or fgets, then parse them as appropriate.
G10: Format source consistentlyFormat all submitted C source files and pass the exercise formatter checks.

G0: Compile and terminate without warnings

Your program must always compile successfully. Overall, CS1010 compiles C code using the C23 standard with -std=c23. We may add “flags” into your Makefile or ask you to add them yourself for specific exercises: we will grade your code based on these flags!

Even if your code compiles, the compiler should not emit any warnings. Similarly, we may change the flags we define for your exercise.

Your program must also always terminate (e.g., no infinite loops) when running on valid inputs as specified by the exercise.

G1: Avoid Undefined Behaviour

Submitted code should not (under reasonable circumstances) execute behaviour that the C23 standard calls “undefined behaviour”. This includes, for example, dividing by zero, reading uninitialized storage, using an object after it has been freed, and freeing an object twice.

Why: Once a program has undefined behaviour, the C standard places no requirements on its result. The program may appear to work, fail unpredictably, or be transformed unexpectedly by the compiler.

When sanitizers are enabled, the program must produce no sanitizer reports. This requirement applies even when the program prints the expected output.

G2: Make code intent clear

This is potentially the most extensive (and maybe subjective) rule - but it’s extremely important!

Make the intent of your code clear through comments, structure, and the way the code is written. Use comments mainly for for important reasoning and decisions. Name your variables appropriately. Divide program flow into manageable, logical pieces, and keep function interfaces focused and appropriately encapsulated.

Why: Clear comments, focused structure, and precise interfaces make the program’s purpose and assumptions visible. They help readers understand the code without reconstructing unnecessary indirection or unrelated implementation details.

G3: Use appropriate numeric types

For CS1010’s numeric types (by default):

  • Use char by default for character types
  • Use int by default for integral types
  • Use unsigned int if you know the value is always non-negative
  • Use double if your values might not only be whole numbers

G4: Use const when a value or pointee should not be modified

Use the const modifier when a value or pointee should not be modified. This makes your intent clear and allows the compiler to catch accidental changes.

G5: Use booleans instead of integers where applicable

C23 provides bool, true, and false directly.

Why: bool, true, and false show that a value represents a condition, so the code is easier to read and less likely to treat arbitrary numbers as flags.

G6: Avoid global variables where possible

When there is no good reason for state to exist outside a function, keep it local and pass it through parameters and return values. Avoid global variables where possible. State that must be shared by a whole module may have a good reason to exist outside a function.

Why: Parameters and return values make a function’s dependencies visible, which makes the function easier to understand, test, and reuse. Mutable global state hides dependencies and makes functions harder to test and reason about.

G7: Use structured control flow instead of goto

Do not use goto in your code (you can see the famous article Go To Statement Considered Harmful).

Why: Structured control flow keeps the paths through a function visible and makes it easier to reason about initialization, cleanup, and error cases.

G8: Don’t leak memory

Do not leak memory (e.g., it must be freed by the end of the program). We will specify in your labs / volumes whether your code is responsible for freeing certain memory, or whether our code will do so instead,

Why: Releasing owned memory when it is no longer needed prevents the program from wasting memory during long-running work or repeated operations.

G9: Read input safely

Do not use scanf anywhere in code you write or change. This is a complete prohibition, including when the input appears simple or bounded. When an exercise requires input reading, use getline or fgets to read a line, then use sscanf where appropriate to parse it.

Why: Reading a bounded line first separates input from conversion, limits how much data is read, and makes it possible to check whether parsing succeeded.

fgets bounds the input read, and sscanf parses the line that was read. Use getline when the exercise requires input lines of unbounded length.

G10: Format source consistently

Format all submitted C source files. WebTop formats C files on save in Vim, Neovim, and the supported nano save flows. You can also run make format. Submission checks reject code that would change when formatted.

Why: One formatter gives everyone the same layout, keeps diffs focused on meaningful changes, and lets automated checks enforce the standard reliably.

The formatter uses the .clang-format file supplied with the exercise. Run make format after the final edit and review the result.