C Conditional Statements - Tricky MCQ
Tricky Questions on Conditional Statements
Basic Level (15 Questions)
What is the output of: if (0.1) printf("True"); else printf("False");
In C, any non-zero value is considered "true" in a conditional context. 0.1 is a non-zero floating-point value, so it evaluates to true. This applies to all numeric types, not just integers.
What is the issue with: if (x = 5) { ... }
This is a classic C pitfall. = is assignment, not comparison (==). The expression x = 5 assigns 5 to x and returns 5, which is non-zero (true). This changes x unexpectedly and the if-block always executes. Some compilers warn about this (use -Wall flag).
What is dangling else problem in C?
The "dangling else" problem occurs when there are nested if statements without else blocks, making it ambiguous which if an else belongs to. C resolves this by associating else with the nearest unmatched if. Always use braces to avoid ambiguity.
What is the output: int x = 1; if (x) { x = 0; } else if (x = 0) { x = 2; } printf("%d", x);
Initially x=1, so the first if condition (x) is true (non-zero). It executes x=0. The else-if is not evaluated because the first if was true. So printf prints 0. Note: else if (x = 0) contains an assignment (=), not comparison (==), which would assign 0 to x and evaluate to 0 (false).
Which is NOT equivalent to if(x) { ... }?
if(x) checks if x is non-zero. if(x == 1) only checks if x equals exactly 1. These are different: if x=2, if(x) is true but if(x == 1) is false. if(!!x) is equivalent (double negation converts to 0 or 1). For pointers, if(x != NULL) is equivalent to if(x).
What is "short-circuit evaluation" in C conditionals?
Short-circuit evaluation means logical operators (&& and ||) evaluate only until the result is determined. For &&: if left operand is false, right isn't evaluated (result is false). For ||: if left operand is true, right isn't evaluated (result is true). This is useful for checking preconditions like if (ptr != NULL && ptr->value > 0).
What is the output: int x = 0; if (x = 1, x == 0) printf("A"); else printf("B");
The comma operator evaluates expressions left-to-right and returns the value of the rightmost expression. Here: (x = 1, x == 0) first assigns 1 to x, then evaluates x == 0 which is false (1 == 0). So the if condition is false, else executes, printing "B".
What is the difference between else-if ladder and nested if-else?
An else-if ladder checks conditions sequentially until one is true, then skips the rest. Nested if-else creates a hierarchy where inner conditions are checked only if outer conditions are true. They have different control flow and performance implications.
What is the output: int a = 5, b = 10; if (a = b) printf("Equal"); else printf("Not Equal");
This is another assignment-in-condition pitfall. a = b assigns b's value (10) to a, and the expression evaluates to 10 (non-zero, true). So "Equal" prints. Both a and b become 10. To compare, use a == b.
Which statement about switch is NOT true compared to if-else ladder?
switch cases can only have constant integral expressions, not complex conditions. if-else can handle any boolean expression. switch is limited to char, int, enum (and in C99, bool). Compilers can optimize switch with jump tables for dense cases. Fall-through (executing multiple cases) happens without break.
What is "if-else expression equivalence" using ternary operator?
The ternary operator ? : is an expression (returns a value) while if-else is a statement (doesn't return a value). This allows ternary to be used in places where if-else can't: initializations, function arguments, return statements, etc. Both expr1 and expr2 must be of compatible types.
What happens in: if (x) { } else { } with no code in blocks?
Empty if-else blocks are syntactically valid but useless. With optimization enabled, the compiler will likely remove them entirely since they have no effect. However, the condition x is still evaluated (possible side effects if x is a volatile variable or function call).
What is "conditional inclusion" using #if, #ifdef?
Preprocessor conditional directives (#if, #ifdef, #ifndef, #elif, #else, #endif) make compile-time decisions about what code to include. They're evaluated before compilation, unlike runtime if statements. Used for platform-specific code, debug builds, feature flags.
What is the output: int x = 0; if (++x || ++x) printf("%d", x);
|| uses short-circuit evaluation. ++x increments x to 1 and returns 1 (true). Since the left operand of || is true, the right operand (++x) is NOT evaluated. So x is incremented only once to 1, and the condition is true. If it were &&, both would be evaluated.
What is "conditional operator precedence" issue?
The ternary operator ?: has very low precedence (just above assignment operators). This often leads to unexpected behavior without parentheses. The expression binds more tightly to operators on the right than on the left. Always use parentheses for clarity in complex expressions.
Hard Level (15 Questions)
What is the type of the controlling expression in `if (ptr)` where ptr is int*?
Scalar converts to int: null pointer becomes 0, non-null non-zero; the condition is effectively an integer comparison to zero.
`switch(1) { case 1: f(); case 2: g(); default: h(); }` calls:
Missing break falls through from case 1 to 2 to default unless stopped.
Case labels in switch must have integer type. Which is INVALID in standard C?
Pointer constants cannot be case labels; character and integer constant expressions are allowed.
`if (x = 0)` where x is int. Effect?
= assigns 0; the value of the assignment expression is 0, which is false in the if condition.
Dangling else problem: `if (a) if (b) x++; else y++;` associates else with:
else binds to the nearest unmatched if—the inner if (b).
`?:` operator precedence relative to assignment?
Conditional ?: is above assignment but below logical OR in precedence.
Given `int x=0; (x==0) ? x=1 : x=2;` — validity?
Both branches may be assignment expressions; the chosen branch runs and assigns.
`if (0.1 + 0.2 == 0.3)` typically:
Floating-point rounding makes the sum slightly different from 0.3; equality compare is usually false.
Which guarantees short-circuit evaluation?
Logical && does not evaluate b if a is false; bitwise & always evaluates both.
`switch` on an enum after incrementing past the last enumerator:
enum values are integers; switch works on the value even if not a named enumerator.
What does `break;` do inside a labeled block `{ L: ... break; }` outside loop/switch?
break is only valid inside loop or switch; labeled statements alone cannot be broken from.
`goto` crossing initialization of variable with automatic storage:
Jumping into scope skips initialization which is a constraint violation / undefined in practice.
`if (sizeof(int) < 0)` — result?
sizeof returns size_t, an unsigned type; compared after usual conversions, never less than zero.
Empty `switch(x) { }` on int x is:
A switch with no case labels is legal though pointless.
`do { ... } while(0);` macro pattern primary benefit?
do-while(0) absorbs a trailing semicolon and forms a single statement in all contexts.