CS U111 · Setup guide · do this once, before the first lab
Setting up a MacBook Air for C
Compiler, terminal, editor, first program, and the compile-run loop you'll use all semester. About 45 minutes, most of it waiting for one download. Nothing here costs money and nothing comes from a random website.
C is a compiled language: you write a text file, a program called a compiler translates it into a runnable program, and then you run that. So you need exactly three things: a compiler, a text editor, and a terminal window to run commands in. Your Mac already ships with the terminal and (almost) the compiler. The only real install is one Apple package. You do not need the full Xcode app (12+ GB), Rosetta, a virtual machine, or any "gcc for Mac" download from a third-party site.
1 · Open the terminal, and learn five commands
Press ⌘+Space, type Terminal, press Return. You get a window with a prompt ending in % — it's waiting for a command. Drag Terminal to the Dock; you'll open it every study session. Five commands cover 95% of what this course needs:
| Command | What it does |
|---|---|
pwd | "print working directory" — which folder am I in? |
ls | list the files in this folder |
cd lab01 / cd .. | move into the folder lab01 / move up one level |
mkdir lab01 | make a new folder |
open . | open the current folder in Finder (handy when you're lost) |
Two habits that make the terminal pleasant instead of painful: press Tab to auto-complete a file or folder name (type cd la, hit Tab, get cd lab01/), and press ↑ to bring back the previous command instead of retyping it. Make a home for the course now:
% mkdir -p ~/cs-u111/lab01
% cd ~/cs-u111/lab01
% pwd
/Users/yourname/cs-u111/lab01
(~ means your home folder. One folder per lab keeps submissions from getting mixed up.)
2 · Install the compiler — one command, then wait
Apple bundles a C compiler in the Command Line Tools. Ask for them:
% xcode-select --install
A dialog pops up; click Install, agree, and wait — it's a 1–2 GB download, typically 10–20 minutes on hostel Wi-Fi. If instead you see command line tools are already installed, you're done already. When it finishes, verify:
% clang --version
Apple clang version 17.0.0 (the numbers will differ — any version is fine)
% gcc --version
Apple clang version 17.0.0 (yes, the same thing — see below)
Course material and lab machines will say gcc, the GNU compiler used on Linux. Apple ships a different compiler, clang, and installs a gcc command that quietly runs clang. For everything in this course — standard C, the textbook's programs, every lab — the two behave the same: same flags, same language, same results. The only visible difference is the wording of error messages (clang's are usually friendlier). So type gcc like everyone else and don't think about it again.
Checkpoint 1: does gcc --version print a version line without an error?
If it says xcrun: error: invalid active developer path, the tools aren't installed yet — run xcode-select --install again and wait for the dialog to finish. If it says command not found, close and reopen Terminal (it only reads the new tools on startup).
3 · An editor: VS Code, kept simple
You can write C in any plain-text editor, but a programmer's editor colours the code and points at mistakes as you type. The standard choice is Visual Studio Code — free, from code.visualstudio.com (choose the Apple Silicon build if asked; the site usually detects it). Then:
- Open VS Code → Extensions (the blocks icon on the left, or ⇧⌘X) → search C/C++ → install the one by Microsoft. That's the only extension you need.
- File → Open Folder… → pick
cs-u111. Always open the folder, not a single file — then the file tree on the left shows every lab. - Optional but worth it: ⇧⌘P → type
shell command→ "Install 'code' command in PATH". Nowcode .in the terminal opens the current folder in VS Code.
Skip "Code Runner"-type extensions and the green run button for now. The lab exam is at a terminal; get comfortable compiling from the terminal first, so nothing about the lab feels foreign. VS Code has a built-in terminal (⌃`) that is the same Terminal — use whichever.
4 · The first program, and the loop you'll run all semester
In VS Code, create a new file inside lab01 called hello.c (the .c matters — it tells the editor and compiler it's C). Type this in — type it, don't paste, so your fingers learn the shape:
#include <stdio.h>
int main(void)
{
printf("Hello from my Mac!\n");
return 0;
}
Save (⌘S). Now in the terminal, inside lab01:
% gcc -Wall -Wextra -std=c11 -o hello hello.c
% ./hello
Hello from my Mac!
Read the first command word by word, because you'll type it hundreds of times: gcc — the compiler. -Wall -Wextra — "warn me about everything suspicious" (more on that in a moment). -std=c11 — use the modern C standard the textbook uses. -o hello — name the output program hello. hello.c — the file to compile. The second command, ./hello, runs the program; the ./ means "the one in this folder".
That's the whole loop, and it never changes:
Edit the .c file → save → compile (↑ brings the command back) → if there are errors, fix the first one only and compile again (later errors are often just fallout from the first) → when it compiles clean, run → test with an input you expect to break it → back to edit. Small steps: change one thing, compile, check. Students who write 80 lines before the first compile spend their evening reading error messages.
Checkpoint 2: delete the semicolon after printf(...), save, compile. What does the compiler say?
Something like hello.c:5:36: error: expected ';' after expression. Decode it: file hello.c, line 5, column 36, and what it expected. The line number is the gift — go there. Errors nearly always point at or just after the real mistake. Put the semicolon back; compile; confirm it's clean again. You just did the loop once.
Warnings are errors that haven't happened yet
With -Wall -Wextra the compiler will sometimes produce a warning and still build the program. Treat every warning as a bug to fix before running — "variable used before it's set", "comparison is always true", "unused variable" are exactly the mistakes that cost lab marks. A clean compile means no output at all from the gcc line. Some instructors compile with -Werror (warnings become errors); adding it yourself is a good habit.
Programs that read input
Most lab programs read numbers from the keyboard. Try one:
#include <stdio.h>
int main(void)
{
int n;
printf("Enter a number: ");
scanf("%d", &n);
printf("Double is %d\n", 2 * n);
return 0;
}
% gcc -Wall -Wextra -std=c11 -o double double.c
% ./double
Enter a number: 21
Double is 42
Two keys to know before your first infinite loop: ⌃C kills a program that won't stop; ⌃D tells a program that's waiting for input that there is no more (this is "end of file" — the file-handling chapter will make it matter).
Checkpoint 3: run ./double and type abc instead of a number. What happens, and why is that a lesson?
You'll get a garbage answer (often Double is 0 or a random number) — scanf failed to read a number and n was never set. No crash, no message: C trusts you. This is why lectures 9 and 39 are about testing with bad input and "defensive programming"; you'll learn to check what scanf returns. For now, just remember: C does what you wrote, not what you meant.
5 · Where a Mac differs from the lab machines
The lab almost certainly runs Linux with GNU gcc (the handout doesn't say — confirm in the first lab and this page will be adjusted). Standard C is standard C, so your programs move across unchanged. The differences that actually bite:
| Situation | On the Mac | What to do |
|---|---|---|
Old tutorials use #include <conio.h>, clrscr(), getch(), void main() | Won't compile — and won't on Linux either. These are 1990s Turbo C, not C. | Ignore any source that uses them. Use int main(void) and return 0;. |
#include <malloc.h> (pointers chapter) | File doesn't exist on macOS. | malloc/free live in <stdlib.h> — correct on every system. |
File names: #include "Utils.h" when the file is utils.h | Works on a Mac (its disk ignores case). | Fails on Linux. Match case exactly; use lowercase names throughout. |
| Error message wording | clang phrases things differently from gcc. | Same errors, same line numbers. Read the line number, not the prose. |
| Debugger | gdb is awkward on Apple Silicon. | Use lldb (already installed) or VS Code's debugger. Honestly: for this course, printf debugging covers 90%. |
| Memory bugs (pointers, arrays out of range) | Often silently "work" on a Mac and crash in the lab, or vice versa. | Compile with -fsanitize=address -g from the arrays chapter onward — it makes the Mac report the bug with the exact line. Best single tool in this list. |
If a lab insists on actual GNU gcc
Unlikely for this course, but possible: install Homebrew (brew.sh, one command), then brew install gcc. It installs as gcc-15 (number varies) so it doesn't shadow Apple's; compile with gcc-15 .... Don't do this pre-emptively — it adds a second compiler to confuse yourself with.
1) Editing the wrong file. You fix the bug, recompile, and nothing changes — because VS Code has hello.c from a different folder open. Check the folder name in the terminal (pwd) matches the tab. 2) Forgetting to recompile. ./hello runs the last compiled version; edits do nothing until you compile again. 3) Smart quotes. If you paste code from a PDF or a chat, “curly quotes” and non-breaking spaces sneak in and produce baffling errors — retype the line. 4) Naming a program the same as a command (-o test): test is a built-in shell command, so ./test is fine but test alone runs the wrong thing. Always run with ./.
6 · A five-minute daily warm-up, once labs start
Open Terminal, cd to the current lab folder, and retype one short program from the last lecture from memory — compile, run, fix. It's the programming equivalent of the maths daily drill: it makes the mechanics automatic (headers, main, semicolons, braces, the compile line), so lab time goes to the actual problem. The 65% of this course that's written on paper, closed book, is precisely a test of whether those mechanics are automatic.
Final checkpoint — all five, then you're set for lab 1
☐ gcc --version prints a version. ☐ hello compiles with no output from the gcc line and prints its message. ☐ You broke it, read the line number, fixed it. ☐ double reads a number and prints twice it. ☐ VS Code has the cs-u111 folder open and the C/C++ extension installed.
An AI is excellent at explaining compiler errors and terrible for your grade if it writes the programs. Prompts that keep you the programmer:
"I'm compiling C on macOS with gcc -Wall -Wextra -std=c11. Here is the error message and the five lines around the line it names. Explain what the message means and what kind of mistake causes it — don't rewrite my code."
"I'm in an intro C course (Hanly & Koffman, chapter 2). Give me three tiny programs to type, each under ten lines, that exercise printf and scanf with different format specifiers — and tell me what output to expect so I can check."
"Quiz me: show a short C program with one bug, let me guess what it prints or where it breaks, then tell me."