Reasoning exercises
Try the C Programming Quiz for a variety of multiple-choice questions on C (but also C++) concepts!
This page presents a series of short, focused problems designed to help you practice and reinforce your understanding of key C concepts. Try to solve each exercise before revealing the answer and explanation.
Tip: you can click on the exercise number to mark it as completed. This helps you keep track of which exercises you've already solved correctly.
Function callingβ
What does the following program print?
#include<iostream>
using namespace std;
int f2(int n) {
cout << n << " ";
return --n;
}
int f3(int n) {
cout << n << " ";
if (n % 2) {
return n - 1;
}
return f2(n - 1);
}
int f(int n) {
if (n == 0) {
return 0;
} else if (n < 4) {
cout << n << " ";
f(f3(n--));
} else if (n < 2) {
return f2(n - 1);
} else {
return f(n - 1);
}
return n;
}
int main() {
cout << f(5);
return 0;
}
Answer
f(5)
:n=5
(β₯4) β returnsf(4)
f(4)
:n=4
(β₯4) β returnsf(3)
f(3)
:n=3
(<4)- prints
3
- calls
f3(3--)
:f3(3)
prints3
and sincen % 2
is 1 (β 0, sotrue
) returns2
- calls
f(2)
- prints
f(2)
:n=2
(<4)- prints
2
- calls
f3(2--)
:f3(2)
prints2
, even β callsf2(1)
f2(1)
prints1
, returns0
f3
returns0
- calls
f(0)
β returns0
f(2)
returns2
- prints
f(3)
returns3
βf(4)
returns3
βf(5)
returns3
main
'scout << f(5)
prints3
Output:
3 3 2 2 1 3
What does the following program print? (functions pointers)
#include <iostream>
using namespace std;
int f1(int p) { return (p * p); }
int f2(int p) { return (p * 2); }
void f(int (*fun1)(int), int (*fun2)(int), int *v, int n) {
for (int i = 0; i < n; i++)
if (i < 2)
v[i] = fun1(v[i] + 1);
else
v[i] = fun2(v[i] + v[i - 2]);
}
int main() {
int a[] = {0, 1, 1, 0};
f(f1, f2, a, 4);
for (int i = 0; i < 4; i++)
cout << a[i] << " ";
cout << endl;
return 0;
}
Answer
How the call works:
f(f1, f2, a, 4);
passes two function pointers (f1
andf2
), the arraya
, and its length4
intof
.- Inside
f
, the parameterfun1
refers tof1
andfun2
refers tof2
. f
then applies these callbacks to array elements based on the index.
Element-by-element computation:
- i = 0 (<2): v[0] = fun1(0+1) = f1(1) = 1Γ1 = 1
- i = 1 (<2): v[1] = fun1(1+1) = f1(2) = 2Γ2 = 4
- i = 2 (β₯2): v[2] = fun2(1 + v[0]) = f2(1+1) = f2(2) = 2Γ2 = 4
- i = 3 (β₯2): v[3] = fun2(0 + v[1]) = f2(0+4) = f2(4) = 2Γ4 = 8
Output sequence:
1 4 4 8
Complete the functions in XXX and YYY so the program prints 4 2 3 15 9
#include <iostream>
using namespace std;
int f1(int n) {
XXX
}
int f2(int n) {
YYY
}
int main() {
int a[] = {1, 4, 2, 3, 9};
for (int i = 0; i < 4; i++) {
if (i % 2)
a[i] = f1(i);
else
a[i] = f2(a[i]);
a[i] = a[i] | a[i + 1];
}
for (int i = 0; i < 5; i++)
cout << a[i] << " ";
}
Solution
The two missing lines are (multiple solutions):
- XXX:
return n * 2;
and YYY:return n / 2;
- XXX:
return n * 2;
and YYY:return n - 1;
- XXX:
return n << 1;
and YYY:return 0;
With these definitions the program outputs:
4 2 3 15 9
What does the following program print? (functions pointers)
#include <iostream>
using namespace std;
int f1(int n) {
return n - 1;
}
int f2(int n) {
return n - 2;
}
int f(int n, int (*fun)(int)) {
if (n < 0)
return n;
if (n % 2 == 0)
return f(fun(n), fun);
else
return f(fun(n), f2);
}
int main() {
cout << f(6, f2);
return 0;
}
Answer
What is fun
?
The parameter fun
in f(int n, int (*fun)(int))
is a pointer to a function that takes an int
and returns an int
. By passing in f1
or f2
, you tell f
which helper function to apply at each recursive call.
Step-by-step evaluation:
- f(6, f2): 6 β₯ 0 and even β f(f2(6)=4, f2)
- f(4, f2): even
β f(f2(4)=2, f2) - f(2, f2): even
β f(f2(2)=0, f2) - f(0, f2): even
β f(f2(0)=β2, f2) - f(β2, f2): n < 0 β returns β2
Final output:
-2
Pointersβ
What does the following program print?
#include <stdio.h>
int main() {
int v[4] = {1, 2, 3, 4};
int *p = v + 1;
int i;
*(p + 2) = 6;
*p = (*p) + 2;
for (i = 0; i < 4; i++) printf("%d ", v[i]);
}
Answer
#include <iostream>
using namespace std;
int main() {
int v[4] = {1, 2, 3, 4};
int *p = v + 1; // p points to v[1] (the second element of v)
int i;
*(p + 2) = 6; // modifies v[3] to 6 (p points to v[1], so p+2 is v[3])
*p = (*p) + 2; // modifies v[1] to v[1] + 2 (so v[1] becomes 4)
for (i = 0; i < 4; i++) cout << v[i] << " ";
// Final array: {1, 4, 3, 6}
}
Notes:
The *
operator has two distinct meanings in pointer-related code:
When declaring a pointer:
int *p;
,*
indicates thatp
is a pointer to an integer. It tells the compiler thatp
will store the address of an integer variable.When dereferencing a pointer:
*p = 10;
,*
is the dereference operator. It accesses the value at the memory address the pointerp
holds, allowing you to read and/or modify that value being pointed to.*(p + n)
accesses the elementn
positions after the onep
points to.
Extra note:
In C and C++, dereferencing a pointer with *(p + 2)
yields an lvalue (referring to a memory location); when used in a context that requires a value (such as printing), this lvalue undergoes an lvalue-to-rvalue conversion to produce the stored value.
Output:
1 4 3 6
What does the following program print?
#include <stdio.h>
void f(int *p, int **rp) {
int *tmp = p;
p = *rp;
*tmp = 10;
*p = 20;
*rp = p;
}
int main() {
int a = 10, b = 10;
int *ptr = &a;
int *prp = &b;
f(ptr, &prp);
printf("%d %d %d %d\n", a, *ptr, b, *prp);
}
Answer
#include <stdio.h>
void f(int *p, int **rp) {
int *tmp = p; // tmp points to a
p = *rp; // p now points to b
*tmp = 10; // sets a = 10
*p = 20; // sets b = 20
*rp = p; // prp still points to b
}
int main() {
int a = 10, b = 10;
int *ptr = &a; // ptr points to a
int *prp = &b; // prp points to b
f(ptr, &prp);
printf("%d %d %d %d\n", a, *ptr, b, *prp);
// Output: 10 10 20 20
}
Explanation:
When we call f(ptr, &prp)
, we're passing a pointer to a
and a pointer to the pointer prp
. Inside the function, tmp
saves the pointer to a
, then p
is redirected to point to b
. We set a
to 10 (which doesn't change its value) and b
to 20. The pointer prp
continues to point to b
. After the function call, a
is 10, ptr
still points to a
so *ptr
is 10, b
is 20, and prp
points to b
so *prp
is 20.
Output:
10 10 20 20
What does the following program print?
#include <stdio.h>
#include <stdlib.h>
void f(int i, int *p, int *ri, int **rp) {
int *q = malloc(sizeof(int)); // or "int *q = new int" in C++
*q = 10;
i = 12;
*rp = q;
*p = (*q)--;
*ri = 19;
(*q)++;
}
int main() {
int a = 5, b = 3;
int *ptr;
ptr = &b;
int *prp;
prp = &a;
f(a, ptr, &b, &prp);
printf("%d %d %d %d\n", a, *ptr, b, *prp);
// Note: memory allocated for q is not freed and no return for simplicity.
}
Answer
#include <stdio.h>
#include <stdlib.h>
void f(int i, int *p, int *ri, int **rp) {
int *q = malloc(sizeof(int)); // Allocate memory for q
*q = 10; // Set q to point to value 10
i = 12; // Local variable change, doesn't affect main
*rp = q; // prp now points to q instead of a
*p = (*q)--; // b gets 10, q now points to 9
*ri = 19; // b is set to 19
(*q)++; // q now points to 10 again
}
int main() {
int a = 5, b = 3; // Initialize variables
int *ptr;
ptr = &b; // ptr points to b
int *prp;
prp = &a; // prp points to a
f(a, ptr, &b, &prp);
printf("%d %d %d %d\n", a, *ptr, b, *prp);
// Output: 5 19 19 10
}
Explanation: The function performs several operations:
a
remains unchanged (5) in main becausei
is passed by valueb
is set to 10 through*p = (*q)--
but then changed to 19 through*ri = 19
ptr
points tob
, so*ptr
is 19prp
initially points toa
but is changed to point toq
which has value 10
Output:
5 19 19 10
What does the following program print?
#include <iostream>
using namespace std;
int main() {
int a[6] = {0, 3, 4, 6, 6, 5};
int *p = &a[2];
a[*p] = a[*(p - 1)];
a[3] = *a;
p = p - 2;
*p = 18;
*(p + 1) = *(p + 3);
for (int i = 0; i < 6; i++) {
cout << a[i] << " ";
}
}
Answer and explanation
At the start the array a
is {0, 3, 4, 6, 6, 5}
and the pointer p
points to a[2]
(value 4
).
- The line
a[*p] = a[*(p-1)];
means βtake*p
(which is4
) as the LHS index, and*(p-1)
(which readsa[1] = 3
) as the RHS index fora
. So we assigna[4] = a[3]
, writing6
intoa[4]
(it stays6
). - Next,
a[3] = *a;
setsa[3]
to the first elementa[0]
, which is0
. - After
p = p - 2;
,p
points back toa[0]
. Then*p = 18;
writes18
intoa[0]
. - Finally,
*(p+1) = *(p+3);
takesa[3]
(now0
) and stores it intoa[1]
, makinga[1] = 0
.
At this point the array is:.
18 0 4 0 6 5