Defensive programming practices - Time & Space Complexity
When writing defensive code, we add checks and safeguards to avoid errors.
We want to see how these extra checks affect how long the program takes to run.
Analyze the time complexity of the following code snippet.
int safe_sum(int *arr, int size) {
if (arr == NULL || size <= 0) {
return 0; // Defensive check
}
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return sum;
}
This code sums numbers in an array but first checks if the input is valid to avoid errors.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The for-loop that adds each array element.
- How many times: It runs once for each element in the array (size times).
The time to run grows directly with the number of elements because each one is added once.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 additions |
| 100 | About 100 additions |
| 1000 | About 1000 additions |
Pattern observation: The work grows steadily as the input grows, no surprises from the checks.
Time Complexity: O(n)
This means the time to finish grows in a straight line with the number of items to add.
[X] Wrong: "Adding defensive checks makes the program much slower for big inputs."
[OK] Correct: The checks run only once and do not grow with input size, so they don't change the main growth pattern.
Understanding how safety checks affect performance shows you care about writing reliable code that still runs efficiently.
"What if we added a nested loop inside the for-loop to check each element against all others? How would the time complexity change?"
Practice
Solution
Step 1: Understand the purpose of defensive programming
Defensive programming is about preventing errors by checking inputs and conditions early.Step 2: Identify the correct goal from options
To check for errors before they cause problems clearly states checking for errors before problems happen, which matches defensive programming.Final Answer:
To check for errors before they cause problems -> Option AQuick Check:
Defensive programming = check errors early [OK]
- Thinking it means ignoring errors
- Confusing it with faster coding
- Believing it removes need for comments
Solution
Step 1: Identify correct NULL pointer check syntax
In C, to check if a pointer is not NULL, use 'ptr != NULL'. Assignment '=' is wrong here.Step 2: Analyze each option
'if (ptr != NULL) { /* use ptr */ }' is correct because it checks that ptr is not NULL before use. B and D use '=' for assignment, setting ptr to NULL/0 and making the condition false. 'if (ptr == 0) { /* use ptr */ }' checks if ptr IS null (equivalent to NULL) and then uses it, causing a null dereference crash.Final Answer:
if (ptr != NULL) { /* use ptr */ } -> Option BQuick Check:
Use '!=' to compare pointer with NULL [OK]
- Using '=' instead of '==' or '!=' in conditions
- Confusing NULL with zero without clarity
- Not checking pointer before use
int *ptr = NULL;
if (ptr != NULL) {
printf("Pointer is valid\n");
} else {
printf("Pointer is NULL\n");
}Solution
Step 1: Analyze pointer initialization
The pointer 'ptr' is set to NULL, meaning it points to nothing.Step 2: Check the if condition
The condition 'ptr != NULL' is false because ptr is NULL, so the else block runs.Final Answer:
Pointer is NULL -> Option AQuick Check:
NULL pointer triggers else block [OK]
- Assuming NULL pointer is valid
- Expecting compilation error
- Thinking no output occurs
void print_length(char *str) {
if (str = NULL) {
printf("String is NULL\n");
return;
}
printf("Length: %d\n", strlen(str));
}Solution
Step 1: Check the if condition syntax
The condition uses 'str = NULL' which assigns NULL to str instead of comparing it.Step 2: Understand impact of assignment in condition
Assignment returns NULL (false), so the if block never runs as intended. It should be 'str == NULL'.Final Answer:
Using assignment '=' instead of comparison '==' in if condition -> Option CQuick Check:
Use '==' to compare pointers, not '=' [OK]
- Confusing '=' and '==' in conditions
- Thinking strlen() is invalid here
- Ignoring function return type
Solution
Step 1: Understand safe input reading
Using scanf requires checking its return value to confirm input was read correctly.Step 2: Validate input range
After reading, check if the integer is within expected limits to avoid errors later.Final Answer:
Check scanf's return value and validate the input range -> Option DQuick Check:
Check input success and validity [OK]
- Ignoring scanf return value
- Using unsafe input functions like gets()
- Assuming user input is always valid
Ready to prove it?
Pass the test and this pattern moves unknown
