PPS-03: Question Bank with MCQs

Comprehensive Zero-Mark Deduction Solutions

Question 1 (Marks: 2)
What is the primary function of the C preprocessor?
  • (A) It translates C code into machine code.
  • (B) It links object files to create an executable.
  • (C) It processes directives before the actual compilation begins.
  • (D) It executes the compiled program.
Click to Reveal Answer & Solution
Correct Answer: (C) It processes directives before the actual compilation begins.
Examiner's Detailed Solution:
Step 1: The C compilation process consists of 4 stages: Preprocessing, Compilation, Assembly, and Linking.
Step 2: The Preprocessor is the very first stage. It handles all directives that begin with the `#` symbol (e.g., `#include`, `#define`, `#ifdef`).
Step 3: It does not understand C syntax. Instead, it performs text substitution—it literally replaces `#include` with the contents of the specified header file, expands macros, and removes comments.
Step 4: Once the preprocessor finishes its text replacement, the expanded source code is passed to the Compiler to be translated into assembly language.
Question 2 (Marks: 2)
Identify the correct way to declare a constant in C.
  • (A) const int x = 10;
  • (B) int const x = 10;
  • (C) #define X 10
  • (D) Both A and B are syntactically correct and identical in meaning.
Click to Reveal Answer & Solution
Correct Answer: (D) Both A and B are syntactically correct and identical in meaning.
Examiner's Detailed Solution:
Step 1: In C, the `const` keyword is a type qualifier used to declare that a variable's value cannot be modified after initialization.
Step 2: `const int x = 10;` and `int const x = 10;` mean exactly the same thing to the compiler: `x` is a constant integer.
Step 3: The `#define X 10` directive creates a preprocessor macro, not a strictly typed C constant variable. A macro is just text substitution and has no memory address or scope in the C sense.
Step 4: Therefore, both A and B are the formally correct ways to declare a constant typed variable in C.
Question 3 (Marks: 2)
What will be the output of the following code?
int x = 5;
if (x = 10) {
    printf("True");
} else {
    printf("False");
}
  • (A) True
  • (B) False
  • (C) Compilation Error
  • (D) Runtime Error
Click to Reveal Answer & Solution
Correct Answer: (A) True
Examiner's Detailed Solution:
Step 1: This question tests the distinction between the assignment operator (`=`) and the equality operator (`==`).
Step 2: Inside the `if` condition, the statement is `x = 10`. This is an assignment, not a comparison.
Step 3: In C, an assignment expression evaluates to the value that was assigned. Therefore, `x = 10` assigns 10 to `x` and evaluates to `10`.
Step 4: In C, any non-zero integer is evaluated as logically `True`. Since 10 is non-zero, the condition is satisfied.
Step 5: The program will enter the `if` block and print 'True'.
Question 4 (Marks: 2)
Which of the following is the correct format specifier to print a memory address (pointer) in C?
  • (A) %m
  • (B) %a
  • (C) %p
  • (D) %x
Click to Reveal Answer & Solution
Correct Answer: (C) %p
Examiner's Detailed Solution:
Step 1: Format specifiers in C tell `printf` and `scanf` what type of data to expect.
Step 2: `%x` or `%X` prints an integer in hexadecimal format. While memory addresses are often displayed in hex, `%x` expects an `unsigned int`, which might be smaller than a pointer on 64-bit systems.
Step 3: The strictly correct and portable format specifier designated by the C standard for printing pointers (memory addresses) is `%p`.
Step 4: When using `%p`, the argument must be cast to `(void *)` to ensure strictly defined behavior according to the C standard.
Question 5 (Marks: 2)
What is the correct syntax to pass an entire 1D array to a function?
  • (A) void func(int arr[])
  • (B) void func(int *arr)
  • (C) void func(int arr)
  • (D) Both A and B are correct.
Click to Reveal Answer & Solution
Correct Answer: (D) Both A and B are correct.
Examiner's Detailed Solution:
Step 1: In C, when you pass an array to a function, you do not pass the entire array by value (which would involve copying all elements).
Step 2: Instead, the array name automatically 'decays' into a pointer to its first element. Therefore, you are passing the base address of the array (Call by Reference).
Step 3: In the function parameter list, `int arr[]` and `int *arr` are completely synonymous. The compiler treats `int arr[]` exactly as `int *arr`.
Step 4: Both explicitly tell the compiler to expect an integer pointer, which points to the start of the array. Hence, both A and B are perfectly valid.
Question 6 (Marks: 2)
If a multidimensional array is declared as `int matrix[3][4];`, how is the element at row index 1 and column index 2 accessed internally using pointer arithmetic?
  • (A) *(*(matrix + 1) + 2)
  • (B) *(matrix + 1 * 4 + 2)
  • (C) *(matrix + 1) + 2
  • (D) **(matrix + 1 + 2)
Click to Reveal Answer & Solution
Correct Answer: (A) *(*(matrix + 1) + 2)
Examiner's Detailed Solution:
Step 1: The array `matrix` is an array of 3 arrays, where each sub-array holds 4 integers.
Step 2: The name `matrix` decays to a pointer to its first row. `matrix + 1` points to the entire second row (row index 1).
Step 3: Dereferencing this, `*(matrix + 1)`, gives us the array representing the second row, which decays into a pointer to its first integer element.
Step 4: To access the 3rd element (column index 2) of that row, we add 2 to that base pointer: `*(matrix + 1) + 2`.
Step 5: Finally, to get the actual integer value stored at that address, we dereference the entire expression: `*(*(matrix + 1) + 2)`.
Question 7 (Marks: 2)
What happens if a function explicitly declares a return type of `int` but lacks a `return` statement?
  • (A) It returns 0 by default.
  • (B) It returns a garbage value / leads to undefined behavior.
  • (C) The compiler automatically converts the return type to void.
  • (D) It causes an immediate runtime crash.
Click to Reveal Answer & Solution
Correct Answer: (B) It returns a garbage value / leads to undefined behavior.
Examiner's Detailed Solution:
Step 1: According to the C standard, if a function has a non-void return type (like `int`), it is strictly expected to execute a `return` statement with a corresponding value.
Step 2: If execution reaches the closing brace `}` of the function without encountering a `return` statement, the function finishes.
Step 3: However, if the caller attempts to read and use the returned value of this function, the result is completely Undefined Behavior.
Step 4: In practice, the caller will read whatever residual data happens to be sitting in the CPU register (typically EAX/RAX) used for return values, resulting in a random garbage value.
Question 8 (Marks: 2)
Which string function is used to concatenate (join) two strings?
  • (A) strcpy()
  • (B) strcmp()
  • (C) strlen()
  • (D) strcat()
Click to Reveal Answer & Solution
Correct Answer: (D) strcat()
Examiner's Detailed Solution:
Step 1: String handling functions are available in the `` library.
Step 2: `strcpy(dest, src)` copies the source string into the destination.
Step 3: `strcmp(s1, s2)` compares two strings lexicographically.
Step 4: `strlen(s)` calculates the length of a string excluding the null terminator.
Step 5: `strcat(dest, src)` stands for string concatenation. It appends a copy of the source string to the end of the destination string, overwriting the destination's original null terminator and appending a new one at the end of the combined string.
Question 9 (Marks: 2)
In a C structure, what is "padding"?
  • (A) Extra memory added by the compiler to satisfy hardware alignment requirements.
  • (B) The metadata stored at the beginning of a struct.
  • (C) The unused memory resulting from dynamic allocation.
  • (D) A technique to compress struct data.
Click to Reveal Answer & Solution
Correct Answer: (A) Extra memory added by the compiler to satisfy hardware alignment requirements.
Examiner's Detailed Solution:
Step 1: CPUs read memory most efficiently when data is aligned to specific word boundaries (e.g., 4-byte or 8-byte boundaries depending on the architecture).
Step 2: When you define a `struct` with mixed data types (like a `char` followed by an `int`), the `char` takes 1 byte, but the `int` must start on a 4-byte boundary.
Step 3: To satisfy this hardware requirement, the C compiler implicitly inserts invisible, unused bytes (padding) between the members, or at the end of the struct.
Step 4: This is why the `sizeof()` a struct is often larger than the mathematical sum of the sizes of its individual members.
Question 10 (Marks: 2)
When opening a file, what does the mode `"r+"` signify?
  • (A) Open an existing file for reading only.
  • (B) Create a new file for reading and writing.
  • (C) Open an existing file for both reading and writing.
  • (D) Append to a file while allowing reading.
Click to Reveal Answer & Solution
Correct Answer: (C) Open an existing file for both reading and writing.
Examiner's Detailed Solution:
Step 1: The `fopen()` function dictates how a file can be accessed.
Step 2: `"r"` opens a file exclusively for reading. The file must exist.
Step 3: `"r+"` (Read/Update) extends `"r"` by also allowing writing. Crucially, the file **must already exist**. It will not create a new file if it's missing.
Step 4: When opened in `"r+"` mode, the file pointer is placed at the very beginning of the file. If you write immediately, you will overwrite existing characters from the start.
Step 5: This is distinct from `"w+"`, which creates a new file (or truncates an existing one to zero length) for reading and writing.