Site icon DataFlair

C Programming Tricky Interview Questions Part-1

interview questions in c part 1

C programming forms the basis of technical interviews at many companies. Interviewers often ask tricky C questions to evaluate a candidate’s understanding of core concepts like pointers, memory management, and flow control. Mastering such questions is key to successfully clearing coding interviews of C.

Why Tricky Questions Matter in C Programming Interviews

Tricky questions in C help assess a candidate’s:

This article of mostly asked interview questions of C will equip you with techniques to tackle such questions and explain the thought process behind arriving at solutions.

Tricky Question 1: Pointers and Arrays in C

The Mystery of Pointer Arithmetic

Pointers and arrays in C have an intimate relationship. Pointer arithmetic in C allows accessing array elements efficiently. But it can also lead to confusing edge cases.

Question 1.1: Swapping Two Integers Using Pointers

Problem: Write a code snippet to swap two integer variables, a and b, using pointer arithmetic.

Question 1.2: Finding the Largest Element in an Array Using Pointers

Problem: Given an integer array arr of size n, find the largest element in the array using pointer arithmetic.

Solution and Explanation

// Swapping two integers using pointers

#include <stdio.h>

void swap(int* a, int* b) {
  int temp = *a;
  *a = *b;
  *b = temp;
}

int main() {

  int a = 10, b = 20;
  
  swap(&a, &b);
  
  printf("a = %d, b = %d", a, b);

  return 0;
}

// Output
a = 20, b = 10

// Finding the largest element using pointers

#include <stdio.h>

int findLargest(int* arr, int n) {
  int max = *arr; // assume first element is largest initially
  
  for(int i=1; i<n; i++) {
    if(*(arr + i) > max) {
      max = *(arr + i); 
    }
  }
  
  return max;
}

int main() {

  int arr[] = {25, 78, 49, 45, 63};
  int n = sizeof(arr)/sizeof(arr[0]);
  
  int largest = findLargest(arr, n);
  
  printf("Largest element is: %d", largest);
  
  return 0;
}

// Output
Largest element is: 78

Tricky Question 2: Memory Allocation in C

Navigating Dynamic Memory Allocation in C

Dynamic allocation with malloc()/free() allows flexible memory management. But when used incorrectly, it can lead to bugs.

Question 2.1: Implementing a Custom Memory Allocator

Problem: Write a custom memory allocator my_malloc() to allocate requested memory dynamically.

Question 2.2: Detecting Memory Leaks in C Programs

Problem: Given a C program, identify potential memory leaks caused by incorrect memory management.

Solution and Explanation

// Custom memory allocator

#include <stdio.h>
#include <stdlib.h>

void* my_malloc(size_t size) {
  void* ptr = malloc(size);
  if(!ptr) {
    printf("Memory allocation failed\n");
    return NULL;
  }

  return ptr;
}

int main() {
  
  int* ptr = (int*)my_malloc(sizeof(int));
  
  if(ptr) {
    *ptr = 100;
    printf("Value at ptr = %d", *ptr);
  }

  return 0;
}

// Output
Value at ptr = 100

For question 2.2, examine the code for mismatches between malloc() and free() calls. Also, ensure all allocated memory is freed before program termination to prevent leaks.

Tricky Question 3: Recursion in C

The Depth of Recursion in C

Recursion allows elegant solutions but can also lead to stack overflows if not written carefully.

Question 3.1: Calculating Fibonacci Numbers Efficiently

Problem: Write a recursive C function to calculate the nth Fibonacci number efficiently.

Question 3.2: Implementing a Recursive Binary Search

Problem: Implement a recursive binary search algorithm on a sorted integer array.

Solution and Explanation

// Efficient Fibonacci using recursion

int fib(int n) {
  if (n == 0 || n == 1) {
    return n;
  }

  int a = 0, b = 1, c, i;
  for(i = 2; i <= n; i++) {
   c = a + b;
   a = b;
   b = c;
  }
  
  return b;
}

// Uses iteration to avoid exponential recursion tree of naive solution.

// Recursive binary search

int binarySearch(int arr[], int l, int r, int x) {

  if (r >= l) {
    int mid = l + (r - l) / 2;

    if (arr[mid] == x) {
      return mid;
    }

    if (arr[mid] > x) {
      return binarySearch(arr, l, mid - 1, x);
    }

    return binarySearch(arr, mid + 1, r, x); 
  }

  return -1;
}

// Recursion reduces code complexity compared to iterative solutions.

Recursion elegantly solves problems like Fibonacci and Binary Search. Care must be taken to avoid costly repeated function calls.

Tricky Question 4: Preprocessor Directives in C

Unraveling the Power of Macros

Preprocessor macros enable metaprogramming but can also lead to unexpected outcomes.

Question 4.1: Creating a Custom ASSERT Macro

Problem: Implement a C macro ASSERT() for debugging that prints an error and exits if the condition is false.

Question 4.2: Conditional Compilation with Macros

Problem: Use preprocessor directives for conditional debugging and logging.

Solution and Explanation

// Custom ASSERT macro

#include <stdio.h>

#define ASSERT(condition, err_msg) \
  if(!(condition)) { \
    fprintf(stderr, "Assertion failed: %s\n", err_msg); \
    exit(1); \
  }

int main() {
  int x = 5, y = 10;
  
  ASSERT(x == y, "x is not equal to y");
  
  printf("Code after ASSERT\n"); // Will not print

  return 0;
}

Macros replace code at the preprocessing stage. This allows the implementation of language extensions like ASSERT.

For question 4.2, use #ifdef DEBUG … #endif to conditionally execute debugging/logging code only in debug builds.

Tricky Question 5: if-else Statements in C

Question 5.1: Printing a Name Without Using a Semicolon

Problem: Print your name using if-else statements without ending the statement with a semicolon.

Question 5.2: Predicting the Output of Complex If/Else Statement

Problem: To print numbers from 1 to 100, create a C program. Print “Fizz” instead of the number for multiples of 3 and “Buzz” for multiples of 5. Print “FizzBuzz” for values that are multiples of both 3 and 5.

Solution and Explanation

// Print name without semicolon

#include <stdio.h>

int main() {
  if(1) 
    if(1)
      printf("John");
  else
    printf("Doe");

  return 0;
}

// Nested ifs allow printing without a semicolon.

#include <stdio.h>

int main() {

  for(int i=1; i<=100; i++) {
    
    if(i%3 == 0 && i%5 == 0) {
      printf("FizzBuzz\n");
    }
    else if(i%3 == 0) {
      printf("Fizz\n");
    }
    else if(i%5 == 0) {
      printf("Buzz\n");
    }
    else {
      printf("%d\n", i); 
    }
  }

  return 0;
}

//Output

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16


Buzz
97
98
Fizz
Buzz

Tricky Question 6: Increment and Decrement Operators in C

Question 6.1: Evaluating Expression x = 5; y = x++ + ++x – –x + x–

Problem: Determine the value of x and y after the given expression.

Question 6.2: Predicting the Output of Complex Increment/Decrement Sequences

Problem: Given the following code snippet, predict the final values of x and y:

int x = 5, y = 10;
x++;
y--;
++x; 
--y;
x++;
y--;

Solution and Explanation

For 6.1, x = 5 originally. Expression is evaluated as:

y = 5 + 7 - 6 + 5 = 11
x = 5

For 6.2, Let’s evaluate the code step-by-step:

Initial values: x = 5, y = 10

x++; // x = 6
y--; // y = 9

++x; // x = 7 (pre-increment)
--y; // y = 8 (pre-decrement)

x++; // x = 8 (post-increment)
y--; // y = 7 (post-decrement)

Therefore, final values after complete execution are:

x = 8
y = 7

The key things to notice are:

Difference between pre and post-increment/decrement
Order in which each statement is executed

Conclusion

Mastering tricky C programming interview questions is a vital skill for acing interviews. This article covered key problem areas like pointers, memory allocation, recursion, data structures, and increment/decrement operators. Analyzing edge cases, understanding nuances, and tracing logical flow are crucial. With rigorous preparation on such questions, you can demonstrate comprehensive C programming knowledge. Practice problems hone the analytical abilities needed for software roles. Strive to write clean, readable code. Mastering core concepts will open up exciting career opportunities.

Exit mobile version