C Programming - ZishanManna/interview-prep-wiki GitHub Wiki

Question 1: What is the difference between a variable and a constant in C?

Click here to reveal the answer
  • A variable is a memory location that holds a value which can change during the program execution.

    int a = 5; // 'a' is a variable that holds the value 5
  • A constant is a value that cannot be altered after it is defined. Constants are defined using the const keyword.

    const int b = 10; // 'b' is a constant that holds the value 10

Question 2: What is the purpose of the main() function in C?

Click here to reveal the answer

The main() function is the entry point of every C program. When the program starts, execution begins from the main() function. It is mandatory in every C program.

Syntax:

int main() {
    // code
    return 0;
}

Question 3: What are the different storage classes in C?

Click here to reveal the answer

C provides four storage classes:

  1. Automatic (auto): Default for local variables.
  2. Register (register): Suggests storing the variable in a CPU register for fast access.
  3. Static (static): Preserves the value of a variable between function calls.
  4. External (extern): Refers to a global variable that is defined elsewhere.

Question 4: What is a pointer in C? Explain with an example.

Click here to reveal the answer

A pointer is a variable that stores the memory address of another variable. Pointers are used for dynamic memory allocation, arrays, functions, and data structures like linked lists.

Example:

int a = 10;
int *p = &a; // `p` is a pointer that stores the address of variable `a`

Here, *p dereferences the pointer, giving access to the value stored in a.


Question 5: Write a C program to find the sum of digits of a given number.

Click here to reveal the answer
#include <stdio.h>

int main() {
    int num, sum = 0;
    printf("Enter a number: ");
    scanf("%d", &num);
    
    while (num != 0) {
        sum += num % 10; // Extract the last digit and add to sum
        num = num / 10;  // Remove the last digit
    }
    
    printf("Sum of digits: %d\n", sum);
    return 0;
}

Explanation: The program takes an integer input and calculates the sum of its digits using a while loop.


Question 6: What is the difference between struct and union in C?

Click here to reveal the answer
  • struct: Allocates memory for all members individually. Every member has its own storage.

    struct example {
        int a;
        float b;
    };
  • union: Shares the same memory location for all members. The size of a union is determined by its largest member.

    union example {
        int a;
        float b;
    };

Question 7: What are preprocessor directives in C?

Click here to reveal the answer

Preprocessor directives are instructions given to the compiler before the actual compilation starts. They begin with a # symbol.

Examples:

  1. #include: Includes the contents of a file.
  2. #define: Defines a constant or macro.
  3. #ifdef / #endif: Conditional compilation.

Question 8: Explain call by value vs call by reference in C.

Click here to reveal the answer
  • Call by Value: A copy of the actual parameter is passed. Changes made to the parameter inside the function do not reflect outside.

    void increment(int a) { a = a + 1; } // Changes are local to the function
  • Call by Reference: The address of the actual parameter is passed, so changes made inside the function affect the original value.

    void increment(int *a) { *a = *a + 1; } // Changes affect the original value

Question 9: What is the use of the volatile keyword in C?

Click here to reveal the answer

The volatile keyword tells the compiler that the value of a variable can change at any time, outside of the control of the code (e.g., a variable modified by hardware). This prevents the compiler from optimizing code involving volatile variables.

volatile int flag = 0;

The flag value will be re-read every time it is accessed.


Question 10: Write a C program to check if a given number is a prime number.

Click here to reveal the answer
#include <stdio.h>

int main() {
    int num, i, flag = 0;
    printf("Enter a number: ");
    scanf("%d", &num);

    if (num <= 1) {
        printf("%d is not a prime number.\n", num);
        return 0;
    }

    for (i = 2; i <= num / 2; i++) {
        if (num % i == 0) {
            flag = 1; // If divisible, then not a prime
            break;
        }
    }

    if (flag == 0)
        printf("%d is a prime number.\n", num);
    else
        printf("%d is not a prime number.\n", num);

    return 0;
}

Explanation: The program iterates from 2 to num/2 to check divisibility. If no divisors are found, the number is prime.


Question 11: What is dynamic memory allocation in C?

Click here to reveal the answer

Dynamic memory allocation refers to the process of allocating memory at runtime using functions like malloc(), calloc(), realloc(), and free(). This allows programs to request memory as needed and release it when no longer in use, helping to manage memory efficiently.

Functions:

  1. malloc(size_t size): Allocates a specified number of bytes.
  2. calloc(size_t num, size_t size): Allocates memory for an array and initializes it to zero.
  3. realloc(void *ptr, size_t size): Resizes previously allocated memory.
  4. free(void *ptr): Frees previously allocated memory.

Example:

int *arr = (int *)malloc(10 * sizeof(int)); // Allocates memory for an array of 10 integers

Question 12: Explain the difference between ++i and i++ in C.

Click here to reveal the answer
  • ++i (Pre-increment): Increments the value of i first and then returns the incremented value.

    int i = 5;
    int a = ++i; // i becomes 6, a is assigned 6
  • i++ (Post-increment): Returns the current value of i and then increments it.

    int i = 5;
    int a = i++; // a is assigned 5, i becomes 6

In summary, the difference lies in when the increment operation takes place relative to the assignment.


Question 13: What are the different types of loops in C?

Click here to reveal the answer

C provides three primary types of loops:

  1. for loop: Used when the number of iterations is known.

    for (int i = 0; i < 10; i++) {
        printf("%d\n", i); // Prints numbers from 0 to 9
    }
  2. while loop: Used when the number of iterations is not known and depends on a condition.

    int i = 0;
    while (i < 10) {
        printf("%d\n", i); // Prints numbers from 0 to 9
        i++;
    }
  3. do-while loop: Similar to the while loop, but guarantees at least one iteration.

    int i = 0;
    do {
        printf("%d\n", i); // Prints numbers from 0 to 9
        i++;
    } while (i < 10);

Question 14: Explain the concept of recursion in C.

Click here to reveal the answer

Recursion is a programming technique where a function calls itself to solve a problem. It is often used for tasks that can be broken down into smaller, similar sub-tasks. A recursive function must have a base case to terminate the recursion and prevent infinite loops.

Example:

#include <stdio.h>

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

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

In this example, the factorial function calls itself with a decremented value until it reaches the base case of 0.


Question 15: What is the difference between strcmp() and strcpy() in C?

Click here to reveal the answer
  • strcmp(): Compares two strings and returns:

    • 0 if the strings are equal,
    • a negative value if the first string is less than the second,
    • a positive value if the first string is greater than the second.

    Example:

    #include <stdio.h>
    #include <string.h>
    
    int main() {
        char str1[] = "Hello";
        char str2[] = "World";
        int result = strcmp(str1, str2);
        printf("Comparison Result: %d\n", result); // Output will depend on the strings
        return 0;
    }
  • strcpy(): Copies the contents of one string into another, including the null terminator.

    Example:

    #include <stdio.h>
    #include <string.h>
    
    int main() {
        char source[] = "Hello";
        char destination[20];
        strcpy(destination, source);
        printf("Copied String: %s\n", destination); // Output: Hello
        return 0;
    }

Question 16: Write a C program to find the largest element in an array.

Click here to reveal the answer
#include <stdio.h>

int main() {
    int n, i, largest;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    
    int arr[n]; // Declare an array of size n

    printf("Enter %d integers:\n", n);
    for (i = 0; i < n; i++) {
        scanf("%d", &arr[i]); // Input elements into the array
    }

    largest = arr[0]; // Assume the first element is the largest

    for (i = 1; i < n; i++) {
        if (arr[i] > largest) {
            largest = arr[i]; // Update largest if current element is greater
        }
    }

    printf("Largest element: %d\n", largest);
    return 0;
}

Explanation: The program prompts the user to enter the number of elements and the elements themselves. It then iterates through the array to find and display the largest element.


Question 17: What is the purpose of the static keyword in C?

Click here to reveal the answer

The static keyword in C serves two main purposes:

  1. Static Variables: When declared inside a function, a static variable retains its value between function calls. It is initialized only once and maintains its state throughout the program execution.

    void counter() {
        static int count = 0; // Initialized only once
        count++;
        printf("%d\n", count); // Prints incremented count on each call
    }
  2. Static Functions: When a function is declared as static, its visibility is limited to the file in which it is defined. This helps in encapsulating functionality and preventing naming conflicts across multiple files.

    static void helperFunction() {
        // This function cannot be called outside this file
    }

Question 18: What is a file pointer in C? How do you use it?

Click here to reveal the answer

A file pointer in C is a pointer that points to a file. It is used for file operations, allowing you to read from and write to files using standard library functions.

File pointer declaration:

FILE *fp;

Common file operations:

  1. Opening a file: Use fopen() to open a file.

    fp = fopen("file.txt", "r"); // Opens a file for reading
  2. Reading from a file: Use functions like fscanf(), fgets(), or fread().

    char buffer[100];
    fgets(buffer, 100, fp); // Reads a line from the file
  3. Writing to a file: Use functions like fprintf(), fputs(), or fwrite().

    fprintf(fp, "Hello, World!\n"); // Writes to the file
  4. Closing a file: Use fclose() to close the file and release resources.

    fclose(fp); // Closes the file

Example:

#include <stdio.h>

int main() {
    FILE *fp;
    fp = fopen("file.txt", "w"); // Open for writing
    if (fp != NULL) {
        fprintf(fp, "Hello, World!\n"); // Write to file
        fclose(fp); // Close the file
    }
    return 0;
}

Question 19: Explain what a segmentation fault is in C.

Click here to reveal the answer

A segmentation fault (often referred to as a "segfault") is a specific kind of error that occurs when a program attempts to access a memory location that it is not allowed to access. This typically happens due to:

  1. Dereferencing a NULL pointer: Trying to access memory using a pointer that has not been initialized.

    int *ptr = NULL;
    printf("%d\n", *ptr); // Causes a segmentation fault
  2. Accessing out-of-bounds array elements: Attempting to read or write beyond the allocated memory for an array.

    int arr[5];
    arr[10] = 25; // Causes a segmentation fault
  3. Stack overflow: Occurs when too much memory is used on the call stack, often due to deep or infinite recursion.

When a segmentation fault occurs, the operating system terminates the program, and an error message is usually printed, indicating the fault.


Question 20: What is the purpose of the enum data type in C?

Click here to reveal the answer

The enum data type in C is used to define a variable that can hold a set of named integer constants. It enhances code readability and maintainability by allowing developers to use meaningful names instead of numeric values.

Syntax:

enum enum_name {
    constant1,
    constant2,
    constant3,
    // ...
};

By default, the first enumerator has the value 0, and each subsequent enumerator's value increments by 1, unless explicitly specified.

Example:

#include <stdio.h>

enum day {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY};

int main() {
    enum day today;
    today = WEDNESDAY;
    printf("Day number: %d\n", today); // Output: 3
    return 0;
}

In this example, the enumeration day is defined, and today is set to WEDNESDAY, which corresponds to the integer value 3.


Question 21: What are pointers in C, and how do you use them?

Click here to reveal the answer

Pointers in C are variables that store the address of another variable. They are used for dynamic memory allocation, arrays, and efficient array manipulation, among other purposes.

Declaration:

int *ptr; // Pointer to an integer

Initialization: You can initialize a pointer by assigning it the address of a variable using the address-of operator (&).

int var = 10;
int *ptr = &var; // ptr now holds the address of var

Dereferencing: To access the value stored at the address a pointer is pointing to, use the dereference operator (*).

printf("%d\n", *ptr); // Outputs: 10

Example:

#include <stdio.h>

int main() {
    int var = 20;
    int *ptr = &var; // Pointer initialization

    printf("Value of var: %d\n", var); // Outputs: 20
    printf("Value via pointer: %d\n", *ptr); // Outputs: 20

    *ptr = 30; // Changing the value of var via pointer
    printf("New value of var: %d\n", var); // Outputs: 30

    return 0;
}

In this example, changing the value via the pointer also updates the original variable.


Question 22: What is the difference between malloc() and calloc() in C?

Click here to reveal the answer

Both malloc() and calloc() are used for dynamic memory allocation in C, but they have key differences:

  1. malloc():

    • Stands for "memory allocation".
    • Allocates a specified number of bytes of memory but does not initialize it.
    • Syntax: void* malloc(size_t size);
    • Returns a pointer to the allocated memory or NULL if the allocation fails.

    Example:

    int *arr = (int *)malloc(5 * sizeof(int)); // Allocates memory for an array of 5 integers
  2. calloc():

    • Stands for "contiguous allocation".
    • Allocates memory for an array of elements and initializes all bytes to zero.
    • Syntax: void* calloc(size_t num, size_t size);
    • Returns a pointer to the allocated memory or NULL if the allocation fails.

    Example:

    int *arr = (int *)calloc(5, sizeof(int)); // Allocates memory for an array of 5 integers and initializes to 0

Key Differences:

  • malloc() allocates memory without initialization, while calloc() allocates and initializes memory to zero.
  • malloc() takes a single argument (total bytes), whereas calloc() takes two arguments (number of elements and size of each element).

Question 23: Explain what a struct is in C and how to use it.

Click here to reveal the answer

A struct (short for structure) in C is a user-defined data type that allows grouping of related variables of different data types under a single name. Structures are useful for organizing complex data.

Syntax:

struct struct_name {
    data_type member1;
    data_type member2;
    // ...
};

Example:

#include <stdio.h>

// Define a struct named 'Person'
struct Person {
    char name[50];
    int age;
};

int main() {
    struct Person person1; // Declare a variable of type struct Person

    // Assign values to the members
    snprintf(person1.name, sizeof(person1.name), "Alice");
    person1.age = 30;

    // Print the values
    printf("Name: %s, Age: %d\n", person1.name, person1.age); // Output: Name: Alice, Age: 30

    return 0;
}

Key Points:

  • Structures allow the combination of different data types into a single unit.
  • You can access the members of a structure using the dot operator (.).

Question 24: What is the purpose of the typedef keyword in C?

Click here to reveal the answer

The typedef keyword in C is used to create an alias for existing data types, making the code more readable and easier to manage. It can be particularly useful when working with complex data types like structures, pointers, and arrays.

Syntax:

typedef existing_type new_type_name;

Example:

#include <stdio.h>

// Create an alias for the 'unsigned long' data type
typedef unsigned long ulong;

int main() {
    ulong num = 100000; // Now 'ulong' can be used as an alias for 'unsigned long'
    printf("Number: %lu\n", num); // Output: Number: 100000
    return 0;
}

Usage with Structures:

#include <stdio.h>

struct Point {
    int x;
    int y;
};

// Create an alias for 'struct Point'
typedef struct Point Point;

int main() {
    Point p1; // Now 'Point' can be used instead of 'struct Point'
    p1.x = 10;
    p1.y = 20;
    printf("Point: (%d, %d)\n", p1.x, p1.y); // Output: Point: (10, 20)
    return 0;
}

Key Points:

  • typedef does not create a new data type; it simply creates an alias.
  • It helps improve code readability and maintainability.

Question 25: What is a union in C, and how does it differ from a struct?

Click here to reveal the answer

A union in C is a user-defined data type that allows storing different data types in the same memory location. Unlike structures, where each member has its own memory space, a union shares the same memory space among its members. This means that a union can only hold one of its members at a time.

Syntax:

union union_name {
    data_type member1;
    data_type member2;
    // ...
};

Example:

#include <stdio.h>

// Define a union named 'Data'
union Data {
    int intValue;
    float floatValue;
    char charValue;
};

int main() {
    union Data data; // Declare a variable of type union Data

    // Assign an integer value
    data.intValue = 5;
    printf("Integer: %d\n", data.intValue); // Output: Integer: 5

    // Assign a float value (overwrites the previous value)
    data.floatValue = 3.14;
    printf("Float: %f\n", data.floatValue); // Output: Float: 3.140000

    // The intValue is now undefined since we assigned a new value to the union
    printf("Integer after float assignment: %d\n", data.intValue); // Output may be undefined

    return 0;
}

Key Differences Between struct and union:

  • Memory Allocation: In a struct, each member has its own memory, while in a union, all members share the same memory location.
  • Data Storage: A struct can store values of all its members at the same time, while a union can only store one member value at a time.

Question 26: Explain the use of const in C.

Click here to reveal the answer

The const keyword in C is used to declare variables whose values cannot be modified after initialization. This provides a way to protect variables from being altered unintentionally and can help improve code safety and readability.

Usage:

  • const can be applied to any data type, including basic types, pointers, and structures.

Example:

#include <stdio.h>

int main() {
    const int MAX = 100; // MAX is a constant integer
    // MAX = 200; // This would cause a compilation error

    printf("Maximum value: %d\n", MAX);
    return 0;
}

Const with Pointers: When using const with pointers, there are two scenarios:

  1. Pointer to a constant value:

    const int *ptr; // Pointer to an int that cannot be modified through ptr
  2. Constant pointer:

    int *const ptr; // Pointer that cannot point to a different address

Example of Pointer to Constant:

#include <stdio.h>

void printValue(const int *p) {
    // *p = 10; // This would cause a compilation error
    printf("Value: %d\n", *p);
}

int main() {
    int num = 5;
    printValue(&num);
    return 0;
}

Key Points:

  • const helps prevent accidental modifications to variables.
  • It can improve the optimization potential of compilers by providing additional information.

Question 27: What is recursion in C? Provide an example.

Click here to reveal the answer

Recursion in C refers to a function calling itself directly or indirectly to solve a problem. It breaks down a problem into smaller sub-problems, each of which is a smaller instance of the same problem. A recursive function typically has two components:

  1. Base case: A condition under which the function stops calling itself.
  2. Recursive case: The part of the function that includes the recursive call.

Example: Calculating the factorial of a number using recursion.

#include <stdio.h>

// Recursive function to calculate factorial
int factorial(int n) {
    if (n == 0) // Base case
        return 1;
    else
        return n * factorial(n - 1); // Recursive case
}

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

In this example, the factorial function calls itself with a decremented value until it reaches the base case of 0. Each function call waits for the result of the next call, building the final result as the calls return.

Key Points:

  • Recursion can lead to elegant solutions but can also consume more stack space compared to iterative solutions.
  • Care must be taken to define a proper base case to avoid infinite recursion.

Question 28: What is the difference between ++i and i++ in C?

Click here to reveal the answer

The expressions ++i and i++ both increment the value of i by 1, but they differ in their behavior regarding the timing of the increment operation.

  1. ++i (Pre-increment):

    • Increments the value of i before the value is used in an expression.
    • The expression evaluates to the new value of i.

    Example:

    int i = 5;
    int result = ++i; // i is incremented to 6, and result is assigned the value 6
    printf("i: %d, result: %d\n", i, result); // Output: i: 6, result: 6
  2. i++ (Post-increment):

    • Increments the value of i after the value is used in an expression.
    • The expression evaluates to the original value of i.

    Example:

    int i = 5;
    int result = i++; // result is assigned the original value 5, and then i is incremented to 6
    printf("i: %d, result: %d\n", i, result); // Output: i: 6, result: 5

Key Points:

  • Use ++i when you need the incremented value immediately.
  • Use i++ when you need to use the original value first before the increment.

Question 29: What are macros in C, and how do you define them?

Click here to reveal the answer

Macros in C are preprocessor directives that define a name for a piece of code. They are used for code substitution and can simplify complex expressions, enable code reuse, and make programs more readable.

Defining Macros: Macros are defined using the #define preprocessor directive. The syntax is as follows:

#define MACRO_NAME replacement_code

Example:

#include <stdio.h>

// Define a macro for the square of a number
#define SQUARE(x) ((x) * (x))

int main() {
    int num = 5;
    int result = SQUARE(num); // Expands to ((5) * (5))
    printf("The square of %d is %d\n", num, result); // Output: The square of 5 is 25
    return 0;
}

Key Points:

  • Macros can take parameters, allowing for more complex substitutions.
  • Be cautious with macros as they are expanded inline and do not respect variable scope. This can lead to unexpected results, especially with expressions.
  • Parentheses are often used in macro definitions to ensure the proper order of operations.

Question 30: What is the difference between break and continue statements in C?

Click here to reveal the answer

The break and continue statements in C are used to control the flow of loops, but they serve different purposes.

  1. break Statement:

    • Used to exit from a loop or switch statement immediately.
    • When a break statement is encountered, the control is transferred to the statement following the loop or switch.

    Example:

    #include <stdio.h>
    
    int main() {
        for (int i = 1; i <= 5; i++) {
            if (i == 3) {
                break; // Exit the loop when i equals 3
            }
            printf("%d ", i); // Output: 1 2
        }
        printf("\nLoop exited.\n");
        return 0;
    }
  2. continue Statement:

    • Used to skip the current iteration of a loop and move to the next iteration.
    • When a continue statement is encountered, the control jumps to the loop's next iteration.

    Example:

    #include <stdio.h>
    
    int main() {
        for (int i = 1; i <= 5; i++) {
            if (i == 3) {
                continue; // Skip the rest of the loop body when i equals 3
            }
            printf("%d ", i); // Output: 1 2 4 5
        }
        printf("\nLoop completed.\n");
        return 0;
    }

Key Points:

  • break is used to terminate the loop, while continue is used to skip to the next iteration.
  • Both statements can be used within for, while, and do-while loops.

⚠️ **GitHub.com Fallback** ⚠️