C Miscellaneous Interview Questions

Last Updated : 15 Nov, 2025

C programming isn't just about printf() and for loops. For technical interviews, especially in system-level, embedded, or product-based roles, you're expected to master the language’s advanced concepts: low-level memory operations, file access, type definitions, and even how programs interact with the OS.

1. What is recursion in C and write a recursive code to compute factorial?

Recursion is the process of making the function call itself directly or indirectly. A recursive function solves a particular problem by calling a copy of itself and solving smaller subproblems that sum up the original problems. Recursion helps to reduce the length of code and make it more understandable. The recursive function uses a LIFO ( Last In First Out ) structure like a stack. Every recursive call in the program requires extra space in the stack memory.

For more information, refer to the article - Recursion

Factorial of a Number C
#include <stdio.h>

int factorial(int n) {
    if (n == 0) return 1;      // Base case
    return n * factorial(n-1); // Recursive call
}

int main() {
    int num = 5;
    printf("Factorial of %d is %d\n", num, factorial(num));
    return 0;
}

2. What is a stack overflow in recursion? How can it be avoided?

Stack overflow occurs when too many recursive calls exceed the function call stack limit. Avoid by:

  • Adding base cases correctly
  • Limiting recursion depth
  • Using iterative approach (tail recursion or loops)

Example:

void recurse() {
recurse(); // No base case -> infinite calls -> crash
}

3. Implement structure & union in C?

  • Structure: The structure is a keyword that is used to create user-defined data types. The structure allows storing multiple types of data in a single unit. The structure members can only be accessed through the structure variable.
  • Union: A union is a user-defined data type that allows users to store multiple types of data in a single memory location. A union does not occupy the sum of the memory of all members. It holds the memory of the largest member only. Since the union allocates one common space for all the members we can access only a single variable at a time.
C
#include <stdio.h>

struct Student {
    int id;
    float marks;
    char grade;
};

int main() {
    struct Student s1 = {101, 89.5, 'A'};

    printf("ID: %d, Marks: %.1f, Grade: %c\n", s1.id, s1.marks, s1.grade);
    return 0;
}

Below is the C program to implement Union:

C
#include <stdio.h>

union Data {
    int i;
    float f;
    char c;
};

int main() {
    union Data d;

    d.i = 10;
    printf("Int: %d\n", d.i);

    d.f = 12.34;
    printf("Float (overwrites int): %.2f\n", d.f);

    d.c = 'A';
    printf("Char (overwrites float): %c\n", d.c);

    return 0;
}

4. How do you read a whole text file line by line in C?

To read a file line by line, you can use the fgets() function, which reads until a newline character or the specified buffer size is reached. This is useful for processing text files without loading the entire file into memory.

How it works:

  • fgets() reads at most sizeof(line): 1 characters from the file, stopping at a newline or EOF.
  • Loop continues until EOF (end of file) is reached.
  • Always check if fopen() succeeds before reading.
C
#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "r");
    char line[256];

    if (fp == NULL) {
        printf("Error opening file.\n");
        return 1;
    }

    while (fgets(line, sizeof(line), fp)) {
        printf("%s", line);  // Print each line as read
    }

    fclose(fp);
    return 0;
}

5. What is an r- value and l-value?

  • An l-value (locator value) refers to an object that has an identifiable memory location (i.e., an address). A modifiable l-value can appear on the left-hand side of an assignment.
  • An r-value (read value) is a temporary value that does not persist beyond the expression and usually does not have a distinct memory address. R-values can appear only on the right-hand side of an assignment.
C
#include <stdio.h>

int main() {
    int val = 20;  // val = l-value, 20 = r-value
    int *p = &val; // valid: l-value has an address

    printf("val (l-value) = %d, &val = %p\n", val, (void*)&val);
    return 0;
}

You cannot take the address of an r-value like &20 or assign to it directly like 20 = val.

6. What is the sleep() function?

The sleep() function in C suspends execution of the current thread for the specified number of seconds. It takes an unsigned int as an argument. For sub-second delays, use usleep() (microseconds) or nanosleep().

C
#include <stdio.h>
#include <unistd.h>  // for sleep()

int main() {
    printf("Sleeping for 3 seconds...\n");
    sleep(0.9);  
    printf("Awake now!\n");
    return 0;
}

7. What are enumerations?

In C, enumerations (or enums) are user-defined data types. Enumerations allow integral constants to be named, which makes a program easier to read and maintain. For example, the days of the week can be defined as an enumeration and can be used anywhere in the program.

enum enumeration_name{constant1, constant2, ... };

C
// An example program to demonstrate working
// of enum in C
#include <stdio.h>

enum week { Mon, Tue, Wed, Thur, Fri, Sat, Sun };

int main()
{
    enum week day;
    day = Wed;
    printf("%d", day);
    return 0;
}

Output
2

In the above example, we declared ā€œdayā€ as the variable, and the value of ā€œWedā€ is allocated to day, which is 2. So as a result, 2 is printed.

For more information, refer to the article - Enumeration (or enum) in C

8: What is a volatile keyword?

Volatile keyword is used to prevent the compiler from optimization because their values can’t be changed by code that is outside the scope of current code at any time. The System always reads the current value of a volatile object from the memory location rather than keeping its value in a temporary register at the point it is requested, even if previous instruction is asked for the value from the same object. 

C
#include <stdio.h>

volatile int flag = 0; 

void externalEvent() {
    flag = 1;
}

int main() {
    printf("Waiting for flag to change...\n");

    while (flag == 0) {
    }

    printf("Flag changed! Proceeding...\n");
    return 0;
}

Without volatile, the compiler might optimize the while(flag == 0) loop into an infinite loop, assuming flag never changes, because it thinks no code inside main() changes it.

9. Write a C program to print the Fibonacci series using recursion and without using recursion.

Fibonacci Numbers
Fibonacci Numbers
C
// C program to print Fibonacci Series
// with recursion and without recursion
#include <stdio.h>

// Recursive Function to print
// Fibonacci Series
void Fibonacci(int num, int first, int second, int third)
{
    if (num > 0) {
        third = first + second;
        first = second;
        second = third;

        printf("%d ", third);

        // Recursive call for it's
        // n-1 value
        Fibonacci(num - 1, first, second, third);
    }
}

// Driver code
int main()
{
    int num=7;

    printf(
        "Fibonacci Series with the help of Recursion:\n");

    printf("%d %d ", 0, 1);

    // we are passing n-2 because we have
    // already printed 2 numbers i.e, 0 and 1

    Fibonacci(num - 2, 0, 1, 0);

    printf("\nFibonacci Series without Using Recursion:\n");

    int first = 0, second = 1, third = 0;

    printf("%d %d ", 0, 1);

    // Loop will start from 2 because we have
    // already printed 0 and 1
    for (int i = 2; i < num; i++) {
        third = first + second;

        printf("%d ", third);

        first = second;
        second = third;
    }

    return 0;
}

Output
Fibonacci Series with the help of Recursion:
0 1 1 2 3 5 8 
Fibonacci Series without Using Recursion:
0 1 1 2 3 5 8 

10. Write a C program to check whether a number is prime or not.

Number Prime or not
Number Prime or not
C
// C program to check if a
// number is prime
#include <math.h>
#include <stdio.h>

// Driver code
int main()
{
    int num=27;
    int check = 1;

    for (int i = 2; i <= sqrt(num); i++) {
        if (num % i == 0) {
            check = 0;
            break;
        }
    }

    if (num <= 1) {
        check = 0;
    }

    if (check == 1) {
        printf("%d is a prime number", num);
    }
    else {
        printf("%d is not a prime number", num);
    }

    return 0;
}

11. How is source code different from object code?

Source CodeObject Code
Source code is generated by the programmer.object code is generated by a compiler or another translator.
High-level code which is human-understandable.Low-level code is not human-understandable.
Source code can be easily modified and contains less number of statements than object code.Object code cannot be modified and contains more statements than source code.
Source code can be changed over time and is not system specific.Object code can be modified and is system specific.
Source code is less close to the machine and is input to the compiler or any other translator.Object code is more close to the machine and is the output of the compiler or any other translator.
Language translators like compilers, assemblers, and interpreters are used to translate source code to object code.Object code is machine code so it does not require any translation.

12. What will be the output of this code and why?

C
#include <stdio.h>

void increment(int *p) {
    (*p)++;
}

int main() {
    int x = 5;
    increment(&x);
    printf("%d\n", x);
    return 0;
}

Explanation:

  • The function increment takes a pointer to an integer.
  • Inside the function, (*p)++ increments the value at the memory location pointed to by p.
  • Since main passes the address of x, the actual variable x is incremented.
  • Hence, output will be: 6

13. Explain modifiers.

Modifiers are keywords that are used to change the meaning of basic data types in C language. They specify the amount of memory that is to be allocated to the variable. There are five data type modifiers in the C programming language:

  • long
  • short
  • signed
  • unsigned
  • long long
C
#include <stdio.h>

int main() {
    short s = -32768;
    long l = 1000000L;
    unsigned int u = 4294967295U;
    signed int si = -100;
    long long ll = 9223372036854775807LL;

    printf("short: %d\n", s);
    printf("long: %ld\n", l);
    printf("unsigned int: %u\n", u);
    printf("signed int: %d\n", si);
    printf("long long: %lld\n", ll);

    return 0;
}


Output
Factorial of 5 is 120

14. Write a program to check an Armstrong number.

An Armstrong number (also called a narcissistic number) is a number where the sum of its digits raised to the power of the number of digits equals the number itself.

For example: 153 is an Armstrong number because:
13+53+33=1+125+27=1531^3 + 5^3 + 3^3 = 1 + 125 + 27 = 15313+53+33=1+125+27=153

Steps:

  1. Count the number of digits.
  2. Extract each digit and raise it to the power of the digit count.
  3. Add the results.
  4. If the sum equals the original number, it's an Armstrong number.
C
#include <stdio.h>
#include <math.h>

// Function to calculate the number of digits
int countDigits(int n) {
    int count = 0;
    while (n != 0) {
        count++;
        n /= 10;
    }
    return count;
}

int main() {
    int n=153;

    int var = n;
    int sum = 0;

    // Get number of digits
    int D = countDigits(n);

    // Calculate the sum of digits raised
    // to the power D
    while (n > 0) {
        int rem = n % 10;
        sum += pow(rem, D);
        n = n / 10;
    }
    
    // If the sum equals the original number,
    // it's an Armstrong number
    if (var == sum) {
        printf("%d is an Armstrong number \n", var);
    } else {
        printf("%d is not an Armstrong number \n", var);
    }

    return 0;
}


15. Write a program to reverse a given number.

To reverse a number:

  1. Initialize rev = 0.
  2. Extract the last digit using num % 10.
  3. Add it to rev after shifting its digits left: rev = rev * 10 + digit.
  4. Remove the last digit from num using num / 10.
  5. Repeat until num becomes 0.

This way, digits are added in reverse order to rev.

C
// C program to reverse digits
// of a number
#include <stdio.h>

// Driver code
int main()
{
    int n=35687, rev = 0;

    // r will store the remainder while we
    // reverse the digit and store it in rev
    int r = 0;
     while (n != 0)
    {
        r = n % 10;
        rev = rev * 10 + r;
        n /= 10;
    }

    printf("Number After reversing digits is: %d", rev);

    return 0;
}

16. Mention file operations in C.

In C programming Basic File Handling Techniques provide the basic functionalities that programmers can perform against the system. 

File Operations in C
File Operations in C

17. Write a Program to check whether a linked list is circular or not.

A circular linked list is one where the last node points back to the first node, forming a loop. To check if a linked list is circular:

  1. Start from the head node.
  2. Traverse the list using a loop.
  3. If during traversal you come back to the head, it’s circular.
  4. If you reach NULL, it’s not circular.

Alternatively, Floyd’s Cycle Detection Algorithm (Tortoise and Hare) can be used to detect loops more efficiently.

C
// C program to check if the linked list is circular
#include <stdio.h>
#include <stdlib.h>
struct Node {
    int data;
    struct Node* next;
};
int isCircular(struct Node* head)
{

    // If given linked list is null then it is circular
    if (head == NULL) {
        return 1;
    }
    struct Node* ptr;
    ptr = head->next;

    // Traversing linked list till last node
    while (ptr != NULL && ptr != head) {
        ptr = ptr->next;
    }

    // will return 1 if Linked list is circular else 0
    return (ptr == head);
}

struct Node* newnode(int data)
{
    struct Node* first;
    first = (struct Node*)malloc(sizeof(struct Node));
    first->data = data;
    first->next = NULL;
    return first;
}

int main()
{

    struct Node* head = newnode(10);
    head->next = newnode(12);
    head->next->next = newnode(14);
    head->next->next->next = newnode(16);
    head->next->next->next->next = head;

    // if it will be 1 then it means linked list is
    // circularĀ 
    if (isCircular(head)) {
        printf("Linked List is Circular\n");
    }
    else {
        printf("Linked List is Not Circular\n");
    }

    return 0;
}

For more information, refer to the article - Circular Linked List

18. Write a program to Merge two sorted linked lists.

To merge two sorted linked lists into a single sorted list:

  1. Use two pointers, one for each list (l1, l2).
  2. Compare current nodes of both lists
  3. Append the smaller node to the result list.
  4. Move that list's pointer forward.
  5. Repeat until one list ends.
  6. Append the remaining nodes of the other list.
  7. Return the head of the merged sorted list.
C
// C program to merge two sorted
// linked lists
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

// Linked List Node
struct Node {
    int data;
    struct Node* next;
};

/* Pull off the front node of the
   source and put it in dest
 */
void MoveNode(struct Node** destRef,
              struct Node** sourceRef);

/* Takes two lists sorted in increasing order,
   and splices their nodes together to make
   one big sorted list which is returned.  */
struct Node* SortedMerge(struct Node* a, struct Node* b)
{
    /* A dummy first node to hang the
       result on */
    struct Node dummy;

    /* tail points to the last result node  */
    struct Node* tail = &dummy;

    /* so tail->next is the place to add new
       nodes to the result. */
    dummy.next = NULL;
    while (1) {
        if (a == NULL) {
            /* if either list runs out, use the
               other list */
            tail->next = b;
            break;
        }
        else if (b == NULL) {
            tail->next = a;
            break;
        }
        if (a->data <= b->data)
            MoveNode(&(tail->next), &a);
        else
            MoveNode(&(tail->next), &b);
        tail = tail->next;
    }
    return (dummy.next);
}

/* UTILITY FUNCTIONS */
/* MoveNode() function takes the node
   from the front of the source, and
   move it to the front of the dest.
   It is an error to call this with the
   source list empty.

   Before calling MoveNode():
   source == {1, 2, 3}
   dest == {1, 2, 3}

   After calling MoveNode():
   source == {2, 3}
   dest == {1, 1, 2, 3} */
void MoveNode(struct Node** destRef,
              struct Node** sourceRef)
{
    /* The front source node  */
    struct Node* newNode = *sourceRef;
    assert(newNode != NULL);

    /* Advance the source pointer */
    *sourceRef = newNode->next;

    /* Link the old dest off the new node */
    newNode->next = *destRef;

    /* Move dest to point to the new node */
    *destRef = newNode;
}

/* Function to insert a node at the beginning of the
   linked list */
void push(struct Node** head_ref, int new_data)
{
    /* allocate node */
    struct Node* new_node
        = (struct Node*)malloc(sizeof(struct Node));

    /* put in the data  */
    new_node->data = new_data;

    /* link the old list off the new node */
    new_node->next = (*head_ref);

    /* move the head to point to the new node */
    (*head_ref) = new_node;
}

/* Function to print nodes in a given linked list */
void printList(struct Node* node)
{
    while (node != NULL) {
        printf("%d ", node->data);
        node = node->next;
    }
}

/* Driver program to test above functions*/
int main()
{
    /* Start with the empty list */
    struct Node* res = NULL;
    struct Node* a = NULL;
    struct Node* b = NULL;

    /* Let us create two sorted linked lists to test
      the functions
       Created lists, a: 5->10->15,  b: 2->3->20 */
    push(&a, 15);
    push(&a, 10);
    push(&a, 5);

    push(&b, 20);
    push(&b, 3);
    push(&b, 2);

    /* Remove duplicates from linked list */
    res = SortedMerge(a, b);

    printf("Merged Linked List is: \n");
    printList(res);

    return 0;
}

Output
Merged Linked List is: 
2 3 5 10 15 20 

19. What is the difference between fread() and fscanf() in C?

fread() is used for binary file reading, and it reads raw bytes.

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

int main() {
    FILE *fp = fopen("data.bin", "rb");
    char buffer[100];

    if (fp) {
        fread(buffer, sizeof(char), 100, fp);
        fclose(fp);
    }
    return 0;
}

fread(buffer, sizeof(char), 100, fp); // Binary

  • fscanf() is used for text file reading and parses input according to a format string.
C
#include <stdio.h>

int main() {
    FILE *fp = fopen("data.txt", "r");
    char str[100];

    if (fp) {
        fscanf(fp, "%s", str);
        printf("Read string: %s\n", str);
        fclose(fp);
    }
    return 0;
}

fscanf(fp, "%s", buffer); // Text

20. How do you open a file in append mode? What happens if the file doesn't exist?

Use "a" mode in fopen():

FILE *fp = fopen("data.txt", "a");

  • If the file exists: It is opened and the file pointer is moved to the end.
  • If the file doesn’t exist: A new file is created.
C
#include <stdio.h>

int main() {
    FILE *fp = fopen("log.txt", "a");

    if (fp) {
        fprintf(fp, "New log entry\n");
        fclose(fp);
    } else {
        printf("Error opening file\n");
    }

    return 0;
}

21. What is typedef in C?

In C programming, typedef is a keyword that defines an alias for an existing type. Whether it is an integer variable, function parameter, or structure declaration, typedef will shorten the name.

Syntax:

typedef <existing-type> <alias-name>

  • existing type is already given a name. 
  • alias name is the new name for the existing variable.
C
#include <stdio.h>

typedef long long ll;

int main() {
    ll bigNum = 10000000000LL;
    printf("Big number: %lld\n", bigNum);
    return 0;
}

22. How do command-line arguments work in C? Give an example.

In C, command-line arguments allow you to pass values (inputs) to the main() function when a program is run from the command line or terminal.

The main() function has two special parameters:

int main(int argc, char *argv[])

  • argc: (Argument Count) – Total number of arguments passed, including the program name.
  • argv: (Argument Vector) – An array of strings (character pointers), where: argv[0] is the name of the program & argv[1] to argv[argc-1] are the actual command-line arguments
C
#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("Total arguments: %d\n", argc);
    
    for (int i = 0; i < argc; i++) {
        printf("Argument %d: %s\n", i, argv[i]);
    }

    return 0;
}

If the executable is named a.out, run it like this in terminal:

./a.out hello world 123

23. What happens if you forget to close a file in C?

  • File descriptors remain open until the program exits.
  • May lead to memory leaks, file lock issues, or OS-level file handle limits.
  • Always use fclose(fp); to properly release the resource.
C
#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "w");

    if (fp) {
        fprintf(fp, "Hello, World!\n");
        fclose(fp);     
    }

    return 0;
}
Comment