How to Actually Survive Your C Programming Final Exam
I've proctored these exams for nearly two decades, and the pattern is predictable enough to be boring. Students who memorize syntax pass. Students who understand what the machine is actually doing pass with room to breathe. The questions on paper rarely look like the code you write in practice, and that's the whole point. Let's start with something that costs half the class points: the difference between *p++ and (*p)++. These look identical if you're skimming, but one increments the value at the pointer location and leaves the pointer alone, while the other increments the pointer itself after reading the value. In C, postfix increment binds tighter than indirection, so *p++ reads the current value and moves the pointer forward. That's not subtle — it's the language being consistent about precedence rules that most people never bother to memorize properly. Another classic: the question that gives you a loop with i = 0; while (i 3); { printf("%d", i); i++; } and asks what prints. The semicolon after the while statement means the loop body is empty. It spins forever, or until i somehow overflows depending on compiler settings and architecture. Students see { printf... } and assume it's inside the loop. It isn't.
Here's a specific example from my own experience that kept coming back. A student wrote a function that allocated an array with malloc, filled it, and returned the pointer. The caller used it, then called free() on it, then called the function again expecting to reuse the same block. The second call returned a different address. The student insisted the code was "the same." I had to explain that malloc doesn't guarantee returning the same block on repeated calls, and relying on that assumption creates a class of bugs that show up nowhere in testing and everywhere in production. The workaround is to stop treating malloc as a persistent object identity provider and instead treat every returned pointer as opaque and disposable.
C Programming Final Exam Questions And Answers
Below are the types of questions you'll actually see, with explanations that match what graders are looking for rather than what looks good on a cheat sheet. What does this print? int x = 5;
printf("%d %d %d\n", x++, ++x, x--);
The answer is undefined behavior. There is no correct output. You're modifying x three times between sequence points without an intervening sequence point between reads. On GCC with default flags you might see "6 7 5" on one machine and "5 7 6" on another. The g++ manual is explicit about this — it's UB, period. The exam wants you to recognize that, not guess what your laptop happens to print. Write "undefined behavior, multiple unsequenced modifications to x" and move on.
Question 2: Pointer Arithmetic
If int arr[5] = {10, 20, 30, 40, 50}; int *p = arr;, what is the value of p[2] after p += 3? 40. The pointer advances three positions, so p now points at arr[3]. Then p[2] accesses arr[5], which is out of bounds and would be undefined behavior if you actually executed it. But in an exam context they're testing whether you understand that array indexing is pointer arithmetic under the hood — p[2] is literally *(p + 2). If p points at index 3, then p + 2 points at index 5. The answer they want is 50, but a good student should note that accessing arr[5] when the array has only five elements is technically UB. Showing that awareness on the exam separates the careful students from the ones who just do the math blindly.
Question 3: Struct Memory Layout
Given this struct on a 64-bit system, what is sizeof(S)? typedef struct { char a; int b; char c; } S; 16 bytes, not 9. The compiler pads each field to its natural alignment. The struct starts at an 8-byte boundary because int requires 8-byte alignment on this architecture. So the layout is: a at offset 0, 3 bytes of padding, b at offset 4, c at offset 12, and 3 more bytes of trailing padding to make the total size a multiple of 8. This is a question I've seen every exam cycle for twelve years. Students who just add the field sizes get 9 and lose points. Students who know about alignment get 16 and move on.
Question 4: Static Variables
What does this recursive function return when called as f(3)? static int counter = 0;
if (n == 0) return 0;
counter++;
return n + f(n-1); 6. The static variable persists across recursive calls, so counter increments from 0 to 3. But counter doesn't affect the return value directly — the return value is n + f(n-1), which expands to 3 + 2 + 1 + 0. Counter is a distractor. I watch students waste five minutes tracing counter through the recursion when they should just evaluate the return expression. The exam question is testing whether you can separate relevant state from irrelevant state in a function. It's not a trick about static variables at all.
Question 5: File I/O
What happens when you try to read from a file opened with "w" mode? fopen("data.txt", "w") truncates the file to zero length and opens it for writing only. Any attempt to read returns EOF immediately. Students sometimes think "w" means "write and read" — it doesn't. If you need both, you use "w+" or "r+". This shows up on exams as a conceptual check more than a coding exercise. They want to know if you've actually opened files in a real program or just memorized the fopen signature.
Question 6: Preprocessor Macros
Given #define SQUARE(x) x * x, what does SQUARE(2 + 3) evaluate to? 11, not 25. The macro expands textually, not mathematically. It becomes 2 + 3 * 2 + 3, which is 2 + 6 + 3 due to operator precedence. The correct macro definition is #define SQUARE(x) ((x) * (x)) with parentheses around the parameter and the entire expression. I've seen this question in every version of this exam. The lesson isn't about macros specifically — it's about whether you understand that preprocessing is textual substitution, not function evaluation.
Question 7: String Termination
What is the minimum buffer size needed to store the string "hello" in C? 6 bytes. C strings are null-terminated, so "hello" requires five characters plus one '\0'. A buffer declared as char s[5] = "hello"; is actually undefined behavior because it leaves no room for the terminator. The compiler may or may not warn about this. I once graded an exam where a student wrote 5 and got it wrong. The discussion at the grading meeting was exactly whether we should have accepted it given that some compilers do emit warnings. We didn't change the answer key. Good code reserves space for the null terminator. Always.
What These Exams Actually Test
Not what you think. They test whether you can predict what a program does before running it. Hand-tracing exercises dominate because no compiler can verify your understanding — only you can. When you see a question with nested loops, pointers, and indirect calls, the strategy is simple: write down the values of every variable at every step. Use a table. Track the program counter equivalent by noting which line executes next. This takes three minutes for a problem that looks like it should take twenty. The questions that trip people up aren't the hard ones. They're the ones that look easy. A five-line function with a static variable, a pointer alias, and an off-by-one condition will cost you more points than a full implementation question because you'll skim past it and miss the subtlety. I've seen students ace the coding portion and fail the output prediction portion by eight points. The gap isn't skill — it's attention.
The One Thing Most Review Materials Miss
Undefined behavior. Every exam I've ever administered includes at least one question where the technically correct answer is "this is undefined." Students press on and pick the most plausible output instead. The exam writer included the UB specifically to catch people who are guessing rather than evaluating. If you encounter a question with out-of-bounds array access, division by zero through a computed expression, or use of an uninitialized variable, the correct exam strategy is to identify the UB and explain why. Don't try to be clever about what the output "should" be. There are also questions where the answer depends on the platform. sizeof(long) is 4 on Windows x64 and 8 on Linux x64. INT_MAX is the same on both, but the size of int can vary. When an exam question doesn't specify the architecture, it's either expecting you to state your assumption or the answer is independent of it. Learn to spot which case you're in quickly. On my exams I usually specify the environment to avoid this ambiguity. If your exam doesn't, you state "assuming 64-bit Linux with LP64 data model" and proceed.
Final Practical Notes
Bring a calculator. Not a smartphone — those get confiscated. A basic scientific calculator is fine. You'll need it for base conversion questions (binary to hex, two's complement representations) and sometimes for computing memory offsets in struct alignment problems. These are mechanical operations that waste time when done mentally under exam pressure. Practice hand-tracing with actual code, not pseudocode. Pseudocode hides the details that matter in C. A missing semicolon, a comma versus a semicolon in a for loop, the difference between == and = in a condition — these are the things that separate students who write C from students who write something that looks like C. Get a copy of any standard C textbook, go to the chapters on pointers and memory management, and trace through the examples by hand. Not on a computer. By hand. With a pen. The physical act of writing each step forces you to slow down enough to notice what the compiler skips over during optimization. If you want a concentrated set of practice problems, search for past exam papers from universities that publish them openly. Many computer science departments post their old C programming finals online. Work through them under timed conditions. The timing matters because most students finish early but make careless errors, while others don't finish at all. You want to find your pace before the real exam, not discover it while the clock is running.
Memorizing these questions won't help much because professors rotate them. Understanding why each answer is what it is will. The underlying concepts — memory layout, pointer semantics, undefined behavior, macro expansion rules, sequence points — recur in every variation. Focus your study time on those, not on individual problems.
Get the Full Details
