Fundamentals 15 min read

15 Challenging C Language Quiz Questions with Detailed Explanations

This article presents a collection of fifteen C programming quiz questions, each accompanied by the original code, multiple‑choice options, the correct answer, and in‑depth explanations covering topics such as setjmp/longjmp, pointer casting, recursion, sizeof, function pointers, variadic functions, and static variables.

ITPUB
ITPUB
ITPUB
15 Challenging C Language Quiz Questions with Detailed Explanations

Question 1

#include <setjmp.h>
static jmp_buf buf;
int main(void)
{
    volatile int b = 3;
    if (setjmp(buf) != 0)
    {
        printf("%d
", b);
        exit(0);
    }
    b = 5;
    longjmp(buf, 1);
}

The first call to setjmp saves the execution environment and returns 0. longjmp restores that environment and forces setjmp to return the non‑zero value passed (here 1). Consequently the program prints the updated value of b, which is 5 .

Question 2

struct node {
    int a;
    int b;
    int c;
};
struct node s = { 3, 5, 6 };
struct node *pt = &s;
printf("%d
", *(int*)pt);

Casting the pointer pt to int* yields a pointer to the first member of the structure. Dereferencing therefore prints 3 .

Question 3

struct node {
    char a;
    char b;
    short c;
    int d;
};
struct node s = { 3, 5, 6, 99 };
struct node *pt = &s;
printf("%X
", *(int*)pt);

Assuming a typical 32‑bit layout where char is 8 bits, short 16 bits and int 32 bits, the structure is packed without padding. Interpreting the first four bytes as an int yields the hexadecimal value 0x60503 (the exact value may differ on other architectures).

Question 4

int foo(int x, int n){
    int val = 1;
    if (n > 0)
    {
        if (n % 2 == 1) val *= x;
        val *= foo(x * x, n / 2);
    }
    return val;
}

This function implements exponentiation by squaring. It recursively reduces the exponent n while squaring the base x. The final return value is xⁿ.

Question 5

int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int*)(&a + 1);
printf("%d %d
", *(a + 1), *(ptr - 1));
&a

is a pointer to the whole array; adding 1 moves past the array. Casting the result to int* yields a pointer just beyond the last element. Subtracting one gives a pointer to a[4]. Therefore the program prints 2 (the second element) and 5 (the last element).

Question 6

void foo(int[][3]);
int main(void)
{
    int a[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
    foo(a);
    printf("%d
", a[2][1]);
    return 0;
}
void foo(int b[][3])
{
    ++b;               // advance to the second row
    b[1][1] = 9;       // modifies a[2][1]
}

After the pointer increment, b points to the second row {4,5,6}. The assignment b[1][1] = 9 writes into the original third row at position a[2][1]. The printed value is therefore 9 (the original value 8 is overwritten).

Question 7

int a, b, c, d;
a = 3;
b = 5;
c = a, b;      // comma operator
d = (a, b);      // parentheses force comma evaluation
printf("c=%d ", c);
printf("d=%d
", d);

The comma operator has lower precedence than assignment. c = a, b assigns a to c (so c = 3) and discards b. The parenthesised expression (a, b) evaluates a then b, yielding b. Hence d = 5.

Question 8

int a[][3] = {1,2,3,4,5,6};
int (*ptr)[3] = a;               // pointer to an array of 3 ints
printf("%d %d ", (*ptr)[1], (*ptr)[2]);
++ptr;                           // advance to next row
printf("%d %d
", (*ptr)[1], (*ptr)[2]);

The first printf prints the second and third elements of the first row: 2 3 . After incrementing ptr, it points to the second row, so the second printf prints 5 6 .

Question 9

int *f1(void)
{
    int x = 10;   return &x;   // returns address of a local variable – undefined
}
int *f2(void)
{
    int *ptr; *ptr = 10; return ptr;   // returns uninitialised pointer – undefined
}
int *f3(void)
{
    int *ptr = malloc(sizeof *ptr);
    return ptr;          // safe – memory allocated on heap
}

Only f3 is safe because it returns a pointer to dynamically allocated memory. Returning the address of a stack variable ( f1) or an uninitialised pointer ( f2) results in undefined behaviour.

Question 10

int i = 3;   int j;
j = sizeof(++i + ++i);
printf("i=%d j=%d
", i, j);

The sizeof operator does not evaluate its operand, so i remains 3. On a typical 32‑bit system the size of int is 4 bytes, therefore j is 4 .

Question 11

void f1(int*, int);
void (*p[2])(int*, int);
int main(void)
{
    int a = 3;
    int b = 5;
    p[0] = f1;
    p[1] = f1;
    p[0](&a, b);
    printf("%d %d ", a, b);
    p[1](&a, b);
    printf("%d %d
", a, b);
    return 0;
}
void f1(int *p, int q)
{
    int tmp = *p;   *p = q;   q = tmp;   // q is passed by value
}

The function swaps the value pointed to by p with the second argument, but the second argument is passed by value, so only a changes. After each call a becomes 5 while b stays 5. The output is 5 5 5 5 .

Question 12

void e(int);
int main(void)
{
    int a = 3;
    e(a);
    putchar('
');
    return 0;
}
void e(int n)
{
    if (n > 0)
    {
        e(--n);
        printf("%d ", n);
        e(--n);
    }
}

The function recursively decrements n before each call. As the recursion unwinds, it prints the current value of n. The exact sequence for the initial value 3 is 0 0 1 0 0 2 (order depends on the two pre‑decrement operations).

Question 13

typedef int (*test)(float*, float*);
test tmp;

This declares test as a pointer to a function that takes two float* arguments and returns an int. Such typedefs are common for callbacks used by bsearch, qsort, and signal handlers.

Question 14

char p;
char buf[10] = {1,2,3,4,5,6,9,8};
p = (buf + 1)[5];
printf("%d
", p);

The expression accesses

buf[6]</> (the seventh element) which holds the value <strong>9</strong>. It can also be written as <code>5[buf+1]

.

Question 15

#include <stdarg.h>
int ripple(int n, ...)
{
    int i, j, k = 0;
    va_list p;
    va_start(p, n);
    for (j = 1; j < n; ++j)
    {
        i = va_arg(p, int);
        for (; i; i &= i - 1)
            ++k;               // count set bits in i
    }
    va_end(p);
    return k;
}
int main(void)
{
    printf("%d
", ripple(3, 5, 7));
    return 0;
}

The function iterates over the variable‑argument list, counting the number of 1‑bits in each integer using the idiom i &= i - 1. For the arguments 5 (binary 101) and 7 (binary 111) the total number of set bits is 5 , which is printed.

Question 16

int counter(int i)
{
    static int count = 0;   // retains value between calls
    count += i;
    return count;
}
int main(void)
{
    int i, j;
    for (i = 0; i <= 5; ++i)
        j = counter(i);
    printf("%d
", j);
    return 0;
}

The static variable accumulates the sum of the arguments passed to counter. After the loop the sum 0+1+2+3+4+5 equals 15 , which is printed.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Software TestingC languagecoding interviewC programmingprogramming puzzles
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.