What are the final values of a, b, tmp? (What is this doing?)
tmp=3 (save a's original value) β a=5 (copy b to a) β b=3 (copy saved value from tmp to b) Answer: a=5, b=3, tmp=3 This is the classic value swap pattern.
T-04Variable
int a = 10;
int b = a / 3;
int c = a % 3;
double d = (double)a / 3;
What are the values of b, c, d?
b = 10/3 = 3 (integer division truncates) c = 10%3 = 1 (remainder) d = 10.0/3 = 3.333... (cast promotes to double division) Answer: b=3, c=1, d=3.333333
T-05Variable
int a = 1;
a += a++; // undefined behavior warningprintf("%d\n", a);
What is the output? Hint: this is a "trap" question.
This is undefined behavior. Modifying and reading the same variable in a single expression is not guaranteed by the C standard. Different compilers may produce 2, 3, or other results. Lesson: Never mix ++ and assignment on the same variable in a single expression.
T-06Variable
int i = 0, sum = 0;
while (i < 5) {
sum += i;
i++;
}
Trace i and sum after each loop iteration in a table.
Iter
i (before)
sum += i
after i++
1
0
0+0=0
1
2
1
0+1=1
2
3
2
1+2=3
3
4
3
3+3=6
4
5
4
6+4=10
5
Answer: i=5, sum=10 (0+1+2+3+4)
T-07Variable
int n = 12345, rev = 0;
while (n > 0) {
rev = rev * 10 + n % 10;
n /= 10;
}
Trace n and rev after each loop. What does this program do?
Iter
n%10
rev
n
1
5
0*10+5=5
1234
2
4
5*10+4=54
123
3
3
54*10+3=543
12
4
2
543*10+2=5432
1
5
1
5432*10+1=54321
0
Answer: n=0, rev=54321 This program reverses the digits of an integer.
int a[4] = {10, 20, 30, 40};
for (int i = 0; i < 3; i++) {
a[i] = a[i + 1];
}
What is the final state of a? What is this code doing?
i=0: a[0]=a[1] β {20,20,30,40} i=1: a[1]=a[2] β {20,30,30,40} i=2: a[2]=a[3] β {20,30,40,40} Answer: {20, 30, 40, 40} This removes the first element by shifting all elements left (the last element remains duplicated).
T-10Array
int a[5] = {2, 8, 3, 9, 1};
int max = a[0], idx = 0;
for (int i = 1; i < 5; i++) {
if (a[i] > max) {
max = a[i];
idx = i;
}
}
Trace how max and idx change at each step.
i
a[i]
a[i]>max?
max
idx
init
-
-
2
0
1
8
8>2 Yes
8
1
2
3
3>8 No
8
1
3
9
9>8 Yes
9
3
4
1
1>9 No
9
3
Answer: max=9, idx=3
T-11Array
int a[5] = {5, 3, 8, 1, 4};
// First pass of bubble sort (bringing the min to the front)for (int j = 4; j > 0; j--) {
if (a[j-1] > a[j]) {
int tmp = a[j-1]; a[j-1] = a[j]; a[j] = tmp;
}
}
Trace the array state after one pass.
Initial: {5,3,8,1,4} j=4: a[3]>a[4]? 1>4 No β {5,3,8,1,4} j=3: a[2]>a[3]? 8>1 Yes β {5,3,1,8,4} j=2: a[1]>a[2]? 3>1 Yes β {5,1,3,8,4} j=1: a[0]>a[1]? 5>1 Yes β {1,5,3,8,4} Answer: {1, 5, 3, 8, 4} (the minimum value 1 bubbles to the front)
T-12Array
int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
int sum = 0;
for (int i = 0; i < 3; i++) {
sum += a[i][i];
}
What is the value of sum? What does this compute?
a[0][0]=1, a[1][1]=5, a[2][2]=9 sum = 1+5+9 = 15 This computes the trace of a matrix (sum of the main diagonal elements).
Tracing Pointers
T-13Pointer
int a = 10, b = 20;
int *p = &a;
*p = 30;
p = &b;
*p = *p + 5;
int a = 5, b = 10;
int *p = &a, *q = &b;
*p = *q;
*q = 0;
printf("%d %d\n", a, b);
What is the output?
*p=*q β a=10 (copy b's value into a) *q=0 β b=0 Answer: 10 0
T-15Pointer
int arr[4] = {10, 20, 30, 40};
int *p = arr;
printf("%d ", *p);
p += 2;
printf("%d ", *p);
printf("%d ", *(p - 1));
printf("%d\n", p[1]);
What is the output?
p=arr β *p=10 p+=2 β p points to arr[2] β *p=30 *(p-1)=arr[1]=20 p[1]=*(p+1)=arr[3]=40 Answer: 10 30 20 40
T-16Pointer
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr + 1;
int *q = arr + 3;
printf("%d %d %ld\n", *p, *q, q - p);
What is the output?
p=&arr[1] β *p=2 q=&arr[3] β *q=4 q-p = 3-1 = 2 (difference in element count) Answer: 2 4 2
T-17Pointer
int x = 100;
int *p = &x;
int **pp = &p;
**pp = 200;
printf("%d %d %d\n", x, *p, **pp);
What is the output? (Double pointer)
pp β p β x chain. **pp=200 modifies x to 200. x=200, *p=200, **pp=200 (all refer to the same location) Answer: 200 200 200
T-18Pointer
int a[] = {10, 20, 30, 40, 50};
int *p = a;
for (int i = 0; i < 5; i++) {
*(p + i) *= 2;
}
What is the final state of a?
Double each element: {20, 40, 60, 80, 100} *(p+i) is equivalent to a[i]. Manipulating the array via pointer arithmetic.
Tracing Function Calls
T-19Function
voidadd_ten(int x) { x += 10; }
intmain(void) {
int a = 5;
add_ten(a);
printf("%d\n", a);
}
What is the output?
Answer: 5 C uses pass-by-value. x inside add_ten is a copy of a, so changing x has no effect on a.
T-20Function
voidadd_ten(int *px) { *px += 10; }
intmain(void) {
int a = 5;
add_ten(&a);
printf("%d\n", a);
}
What is the output? (Compare with T-19.)
Answer: 15 Because we pass a pointer, *px += 10 modifies a itself.
T-21Function
intmystery(int a, int b) {
a = a + b;
b = a - b;
a = a - b;
return a * 10 + b;
}
printf("%d\n", mystery(3, 7));
What is the output? Trace a and b line by line.
a=3, b=7 a=3+7=10 b=10-7=3 a=10-3=7 return 7*10+3 = 73 This is a swap without a temporary variable. a and b are exchanged, so the result is 7*10+3=73.
T-22Function
voidmodify(int arr[], int n) {
for (int i = 0; i < n; i++) arr[i] *= 3;
}
intmain(void) {
int data[] = {1, 2, 3};
modify(data, 3);
printf("%d %d %d\n", data[0], data[1], data[2]);
}
What is the output? (Array pass vs. int pass)
Answer: 3 6 9 Arrays are passed as pointers, so modifications inside the function affect the caller. This is different from pass-by-value for ints (T-19)!
T-23Function
intfactorial(int n) {
if (n <= 1) return1;
return n * factorial(n - 1);
}
printf("%d\n", factorial(5));
int a[3] = {1, 2, 3};
int *p = a;
for (int i = 0; i < 3; i++) {
a[i] = a[(2-i)];
}
What is the final state of a? (Hint: it does NOT become a reversed array. Why?)
i=0: a[0]=a[2] β {3,2,3} i=1: a[1]=a[1] β {3,2,3} i=2: a[2]=a[0] β {3,2,3} (a[0] is already 3!) Answer: {3, 2, 3} (NOT {3, 2, 1}) Reason: The earlier iterations overwrite the beginning of the array, so later reads pick up already-modified values. A correct reversal needs a temporary array or two-pointer swap.
T-30Mixed
intf(int *a, int *b) {
*a += *b;
*b = *a - *b;
return *a + *b;
}
intmain(void) {
int x = 4, y = 6;
int z = f(&x, &y);
printf("%d %d %d\n", x, y, z);
}
What is the output? (Trace modifications via pointers.)
int a[5] = {5, 2, 8, 1, 9};
for (int i = 0; i < 4; i++) {
if (a[i] > a[i+1]) {
int t = a[i]; a[i] = a[i+1]; a[i+1] = t;
}
}
What is the final state of a? What is guaranteed about it?
i=0: 5>2 β swap β {2,5,8,1,9} i=1: 5>8? No β {2,5,8,1,9} i=2: 8>1 β swap β {2,5,1,8,9} i=3: 8>9? No β {2,5,1,8,9} Answer: {2, 5, 1, 8, 9} It is guaranteed that the maximum value (9) ends up at the last position (one forward-scanning pass of bubble sort).
T-32Mixed
intcount = 0;
for (int i = 1; i <= 100; i++) {
if (i % 3 == 0 && i % 5 == 0)
count++;
}
What is the final value of count? (You don't need to trace everything β find the pattern.)
Divisible by both 3 and 5 β counts multiples of 15. Multiples of 15 in 1..100: 15, 30, 45, 60, 75, 90 β 6 values. Answer: count=6
intgcd(int a, int b) {
while (b != 0) {
int tmp = b;
b = a % b;
a = tmp;
}
return a;
}
printf("%d\n", gcd(48, 18));
Trace a, b, and tmp in each iteration.
Iter
a
b
tmp
a%b
1
48
18
18
48%18=12
2
18
12
12
18%12=6
3
12
6
6
12%6=0
end
6
0
-
-
Answer: 6 (the greatest common divisor of 48 and 18)
T-38Mixed
int *p = (int *)malloc(sizeof(int) * 3);
p[0] = 10; p[1] = 20; p[2] = 30;
int *q = p;
free(p);
// printf("%d\n", *q); β is this safe?
What happens if we access *q after free?
Undefined behavior (dangling pointer). q was pointing to the same location as p, but free(p) released that memory. q still holds the same address, but the memory is no longer valid. Lesson: After free, set all related pointers to NULL too.
T-39Mixed
int a[4] = {10, 20, 30, 40};
int *p = a, *q = a + 3;
while (p < q) {
int t = *p; *p = *q; *q = t;
p++; q--;
}
What is the final state of a? What is it doing?
Iter 1: p=a[0], q=a[3] β swap(10,40) β {40,20,30,10}, p++, q-- Iter 2: p=a[1], q=a[2] β swap(20,30) β {40,30,20,10}, p++, q-- p>=q β exit Answer: {40, 30, 20, 10} This is an in-place array reverse. Swap from both ends toward the center.
T-40Mixed
intbinary_search(int a[], int n, int key) {
int lo = 0, hi = n - 1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (a[mid] == key) return mid;
else if (a[mid] < key) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
// a = {2, 5, 8, 12, 16, 23, 38, 56}, key = 23
Trace lo, hi, mid and state how many iterations it takes to find the key.
Iter
lo
hi
mid
a[mid]
decision
1
0
7
3
12
12<23 β lo=4
2
4
7
5
23
23==23 β found!
Answer: returns index=5 on iteration 2
Want more trace practice?
Tracing problems with pen and paper is the most effective way to prepare for exams
π
The C Programming Language (K&R)
B. W. Kernighan, D. M. Ritchie
The classic C reference. Perfect for stepping up after you have the basics.