Arrays and pointers learning review
Use the review to find a reasoning gap
Solve these twelve original questions after M2-L01 through M2-L06. They revisit array state, scans, pointer targets, calls, boundaries and two-dimensional rows. The review introduces no new examinable concept. It samples each lesson’s core outcomes twice; it does not test every individual objective or replace the teaching exercises.
This is an untimed educational review. The maximum is 12 marks: +1 for each correct answer and 0 for an incorrect or unattempted answer. There are no negative marks, no partial marks and no pass threshold. These local learning settings are not a statement of official GATE marking rules. The questions are original, not official previous-year questions, and this is not a full GATE mock.
- MCQ means choose exactly one option. There are five MCQs
- MSQ means choose the complete set of true options. There are four MSQs. A missing correct option or an extra incorrect option gives 0 for that item
- NAT means supply one signed decimal integer. There are three NATs. Use ordinary digits 0–9 and the keyboard minus sign
-for negative values; surrounding spaces, a leading plus sign and leading zeros are accepted. Decimals, exponents, arithmetic expressions, units and multiple values are not accepted. The integer value must match exactly; tolerance is zero
Use the same response format in either language. The Hindi section is the counterpart of the same twelve items, not twelve additional questions. Answers and full explanations follow all questions so you can attempt the review first.
Conditions for the code
C11 is the course’s teaching convention, not a claimed GATE-mandated version. Every complete program is independent, uses positive fixed-size arrays where shown and starts from its own initialized state. Live target and bound assumptions are stated or established by the displayed code. Every evaluated integer calculation fits within −32767 through 32767; pointer differences shown fit in ptrdiff_t. No int or pointer byte size is assumed. No dynamic allocation or variable-length array is used.
The complete c-fenced programs are defined for the displayed inputs. Text-fenced classification material and invalid expressions mentioned in options must not be compiled or executed. Do not invent numeric outputs for undefined behavior. Any output triple or sequence shown in an answer is followed by the program’s newline.
Questions
01 MCQ Keep the saved integer separate
Choose the printed triple. The three values appear in the order saved, a[1], a[2].
#include <stdio.h>
int main(void)
{
int a[4] = {5, 2, 8, 1};
int saved = a[2];
a[2] = a[0] - a[1];
a[1] = saved + 1;
printf("%d %d %d\n", saved, a[1], a[2]);
return 0;
}A. 8 9 3
B. 3 4 3
C. 8 9 8
D. 8 3 9
02 NAT Start from the complete initialized state
Enter the one integer printed by this program.
#include <stdio.h>
int main(void)
{
int a[5] = {3, 2};
a[4] = a[1] + 4;
a[2] = a[4] - a[3];
a[1] = a[2] + a[0];
printf("%d\n", a[1]);
return 0;
}03 NAT Total only qualifying selected values
Enter the printed total. Keep the selected prefix, qualifying count and value sum distinct.
#include <stdio.h>
int main(void)
{
int a[6] = {4, 9, 2, 7, 5, 8};
int length = 5;
int count = 0;
int total = 0;
for (int i = 0; i < length; i++) {
if (a[i] >= 5) {
count++;
total += a[i];
}
}
printf("%d\n", total);
return 0;
}04 MSQ Keep the first match
Select every true statement. Each proposed change in an option is considered separately from the original program.
#include <stdio.h>
int main(void)
{
int values[5] = {6, 3, 6, 2, 6};
int length = 4;
int target = 6;
int first = -1;
for (int i = 0; i < length; i++) {
if (first == -1 && values[i] == target) {
first = i;
}
}
printf("%d\n", first);
return 0;
}A. The displayed program prints 0 and still executes four loop bodies.
B. Once the first match is recorded, the guard ends the whole loop immediately.
C. Changing only target to 9 leaves first at −1; that marker must not be used as an array index.
D. Removing only first == -1 && makes the displayed target 6 leave first at 2.
05 MCQ Retarget one pointer
Choose the output after both pointers have been traced separately.
#include <stdio.h>
int main(void)
{
int x = 4;
int y = 9;
int *p = &x;
int *q = p;
*q = 6;
p = &y;
*p = *q + 1;
*q = *p + 2;
printf("%d %d %d\n", x, y, *q);
return 0;
}A. 6 12 12
B. 9 7 9
C. 6 7 6
D. 9 9 9
06 MSQ Check the target and its lifetime
Select every true statement under this module’s C11 convention. These are behavior and lifetime claims, not instructions to execute invalid accesses. “Automatic integer” here means an ordinary local integer whose lifetime ends when its block ends.
A. For any pointer whatsoever, testing p != NULL proves that reading *p is safe.
B. A pointer to a live initialized integer containing 0 can be dereferenced; it is different from a null pointer.
C. When an automatic integer’s lifetime ends, every pointer still holding its address automatically becomes null.
D. An integer value copied into an outer live variable before the inner source object ends can remain usable after that inner block ends.
07 MCQ Keep the caller and helper records separate
Choose the output. The selected length is valid for the shown array.
#include <stdio.h>
void raise_prefix(int a[], int length)
{
for (int i = 0; i < length; i++) {
a[i] += 2;
}
length = 1;
}
int main(void)
{
int data[4] = {1, 4, 6, 3};
int selected = 2;
raise_prefix(data, selected);
printf("%d %d %d | %d\n",
data[0], data[1], data[2], selected);
return 0;
}A. 1 4 6 | 2
B. 3 6 6 | 1
C. 3 6 6 | 2
D. 3 6 8 | 2
08 MSQ Follow stores before and after local retargeting
Select every true statement about this complete program after the call returns.
#include <stdio.h>
void change_targets(int *p, int *q)
{
*p = *p + 1;
p = q;
*p = *p + 2;
}
int main(void)
{
int x = 2;
int y = 5;
int *chosen = &x;
change_targets(chosen, &y);
printf("%d %d %d\n", x, y, *chosen);
return 0;
}A. Caller chosen still identifies x.
B. The first store in the helper changes caller x to 3.
C. The assignment p = q makes caller chosen identify y.
D. The final store in the helper changes caller y to 7.
09 NAT Measure the signed element distance
Enter the printed signed integer. Both pointers belong to the same live array, and the difference fits in ptrdiff_t. Do not assume any byte size for int or a pointer.
#include <stddef.h>
#include <stdio.h>
int main(void)
{
int a[6] = {2, 5, 1, 8, 4, 7};
int *p = a + 1;
int *q = p;
p = p + 3;
ptrdiff_t gap = q - p;
printf("%td\n", gap);
return 0;
}10 MCQ Classify the end boundary before reading
This is classification-only material. Do not compile or execute the fragment or the invalid expressions mentioned in the choices. With the declaration below, choose the single correct statement. Consider each proposed expression independently.
int a[3] = {7, 2, 5};
int *end = a + 3;A. end points to an extra integer whose value is implicitly zero.
B. Reading *end must produce the same value as reading a[2].
C. Forming end + 1 is permitted as long as the result is never dereferenced.
D. Forming end is permitted, and *(end - 1) reads 5; reading *end has undefined behavior.
11 MCQ Sum and then update a selected column
Choose the output. The column index remains 1 while the row index changes.
#include <stdio.h>
int main(void)
{
int grid[2][3] = {{4, 1, 6}, {2, 8, 3}};
int column = 1;
int total = 0;
for (int r = 0; r < 2; r++) {
total += grid[r][column];
grid[r][column] += r;
}
printf("%d %d %d\n", total, grid[0][1], grid[1][1]);
return 0;
}A. 9 1 9
B. 10 1 9
C. 6 1 8
D. 9 0 1
12 MSQ Keep rows and elements distinct
Select every true statement about the declarations below. The array and pointer are live. The visit-order statement refers to nested loops with r starting at 0 and increasing by 1 while r < 2, and, inside each outer body, a fresh c starting at 0 and increasing by 1 while c < 3. The inner body visits grid[r][c]. Claims involving an invalid read are for classification only.
int grid[2][3] = {{4, 1, 6}, {2, 8, 3}};
int (*row)[3] = grid;A. row is a pointer to a three-int row; row + 1 identifies the second row, not merely the next integer.
B. The declaration makes grid an int **, so each row is stored as a pointer variable.
C. The stated nested loops visit (0,0), (0,1), (0,2), (1,0), (1,1), (1,2) in that order.
D. Reading grid[1][3] is valid because the complete array contains six integers.
Answers and full solutions
Answer key: 01 A; 02 9; 03 21; 04 A, C, D; 05 B; 06 B, D; 07 C; 08 A, B, D; 09 -3; 10 D; 11 A; 12 A, C
01 Keep the saved integer separate
Answer A. saved copies 8 before either element update. The first store computes 5 - 2 = 3 and changes only a[2]. The second computes 8 + 1 = 9 and changes only a[1]. Final array: {5, 9, 3, 1}; separate saved = 8. Output: 8 9 3, followed by a newline. All accessed indices lie from 0 through 3.
A matches those three current values in the requested order. B lets saved follow the changed element and then uses that imagined 3 in the next calculation. C omits the store to a[2]. D interchanges the two printed element positions.
First check if wrong: draw saved outside the array record and update only the assignment's actual destination. Revisit M2-L01, “Apply the familiar assignment rule to one element” and worked example 1.
02 Start from the complete initialized state
Answer 9. The positive fixed-size array has an initializer list, so its full starting state is {3, 2, 0, 0, 0}. The three stores give {3, 2, 0, 0, 6}, then {3, 2, 6, 0, 6}, then {3, 9, 6, 0, 6}. Thus a[1] is 9. The read of a[3] uses its implicit initial zero, not an uninitialized value. Index 4 is the last valid position of this five-element array.
An answer of 6 stops before the final addition of a[0]. An answer of 7 can result from incorrectly repeating the last initializer 2 into omitted positions. An answer of 2 ignores the later stores. None of the updates reruns the initializer.
First check if wrong: write all five initial entries before tracing. Revisit M2-L01, “Partial initialization supplies the remaining zeros” and worked example 2.
03 Total only qualifying selected values
Answer 21. Only indices 0 through 4 are selected. The visited values are 4, 9, 2, 7 and 5; the value 8 at index 5 is outside the selected prefix. After each body, (count, total) is (0, 0), (1, 9), (1, 9), (2, 16), (3, 21). The loop then fails its test with i = 5 without accessing that position.
Before each test, total is the sum of qualifying values already visited, and count is how many qualified. The array is unchanged. There are five bodies and six loop tests; three inner branches update the accumulators.
An answer of 3 gives the count, not the requested total. 29 incorrectly includes the unselected final value 8. 8 adds the qualifying indices 1, 3 and 4 instead of their values. 5 retains only the last qualifying value.
First check if wrong: draw a boundary after index 4, then record both accumulators at each checkpoint. Revisit M2-L02, worked example 1 and “Say what an accumulator means at a checkpoint”.
04 Keep the first match
Answer A, C and D. In the original program, index 0 matches and stores 0. The remaining three bodies still execute. Their left operand first == -1 is false, so short circuit skips the element comparison and no later assignment occurs. Output: 0, followed by a newline. The loop has four bodies and five loop tests; it does not visit index 4.
A is true: retaining a result and stopping a loop are different actions. B is false: the guard controls the inner assignment, not the outer loop. C is true: none of the selected values equals 9, so −1 remains a not-found marker, never a valid position. D is true: without the first-match guard, indices 0 and 2 each overwrite first; the last selected match is 2. Index 4 also holds 6, but it is outside this chosen length.
First check if wrong: mark which condition skips which operation. Do not infer a loop exit from the variable name first. Revisit M2-L02, worked example 2 and practice 3–4.
05 Retarget one pointer
Answer B. Initially both pointers identify x. The first store through q makes x = 6. Retargeting p gives p → y, while q → x remains. Next *p = *q + 1 makes y = 6 + 1 = 7. Finally *q = *p + 2 makes x = 7 + 2 = 9. The final targets are still different, so *q reads x = 9. Output: 9 7 9, followed by a newline.
A can result from incorrectly making q follow the later retargeting of p: that mistaken trace keeps x = 6 and makes both stores reach y. B is the valid trace. C omits the final store through q. D leaves y at its old 9 despite the store through p.
First check if wrong: after p = &y, redraw only the arrow for p. A copied pointer value does not make the other variable follow future assignments. Revisit M2-L03, worked example 2.
06 Check the target and its lifetime
Answer B and D. A is false. A null comparison only rules out the known null case under suitable prior assumptions; it does not establish that an arbitrary pointer has a valid live target. An uninitialized pointer or one whose target has ended is not repaired by that comparison. We do not execute such a comparison to “check” it.
B is true. The target's integer value 0 and the pointer's nullness are different facts. A valid pointer to that initialized object supplies a readable integer zero.
C is false. A pointer value still referring to an object whose lifetime has ended becomes indeterminate under our C11 convention, not automatically null. Keeping the pointer variable alive does not prolong its target.
D is true. Copying a known integer into a separate longer-lived integer object preserves that value independently. This is different from retaining a pointer to the ended object. The outer copy must itself still be alive and initialized, as stated.
First check if wrong: draw separate lifetime intervals for the source object, any pointer variable and the copied integer. Revisit M2-L03, “Null is an explicit absence of a target” and “A target has to remain alive”.
07 Keep the caller and helper records separate
Answer C. The array argument supplies a pointer to data[0]; helper parameter a is adjusted to int *. Helper length receives the copied integer 2. The two loop bodies change data to {3, 4, 6, 3} and then {3, 6, 6, 3}. The test fails at index 2, so no later element is changed.
The final helper assignment sets its own length to 1 after the loop. It does not change caller selected = 2. The void helper returns control without a result value, but the element stores have already reached caller storage. Output: 3 6 6 | 2, followed by a newline.
A incorrectly invents a private array copy. B transfers a local parameter assignment back into caller selected. C keeps both records correct. D processes the third element even though the selected prefix has length 2. No hidden array length is supplied by the helper’s brackets.
First check if wrong: draw the real array once and put helper parameters in separate boxes. Revisit M2-L04, worked example 1 and the helper access contract.
08 Follow stores before and after local retargeting
Answer A, B and D. At entry, caller chosen → x, helper p → x, and helper q → y are three separate pointer records. The first body statement reads 2 through p and stores 3 into x. Then p = q retargets only the helper parameter p to y. The final store reads 5 from y and replaces it with 7. Output: 3 7 3, followed by a newline.
A is true because caller chosen was never assigned a new pointer value. B is true because a copied pointer can still identify shared caller storage. C is false because assignment to the helper's pointer object does not assign to the caller's separate pointer object. D is true because the last dereference follows the helper's current target, y.
First check if wrong: mark each statement as a store to an integer or an assignment to a pointer variable. Do not use “passed by reference” as a substitute for the copied-value trace. Revisit M2-L04, worked example 2.
09 Measure the signed element distance
Answer −3. Both pointers start at position 1. The assignment advances only p by three elements, taking it to position 4; q remains at position 1. Thus q - p is 1 - 4 = -3. This counts signed element steps in the stated order, not values stored in the array and not bytes. No dereference occurs, and all formed positions are within this six-element array.
ptrdiff_t is the signed result type used here and %td prints it. An answer of 3 reverses the subtraction. Zero incorrectly moves q together with p. An answer based on 5 and 4 subtracts stored element values rather than positions. Multiplying by an assumed byte size answers a different question.
First check if wrong: label each pointer with (array identity, position) and subtract the position of the right operand from that of the left. Revisit M2-L05, “A distance between positions also has a type” and practice 2.
10 Classify the end boundary before reading
Answer D. A three-element array has readable positions 0, 1 and 2. Pointer position 3 is the permitted one-past boundary. It is useful as a stopping position but supplies no fourth integer. Subtracting 1 from that end pointer returns to position 2, where the initialized value is 5.
A is false: partial-initializer zero filling never creates an extra element. B is false: an evaluated read through the end pointer is undefined, not a second spelling of the last element. C is false: end + 1 attempts position 4, outside even the permitted pointer-formation range 0 through 3. Avoiding a later dereference does not make that formation valid. D states both boundaries correctly.
The unsafe expressions have no prescribed numeric output; neither a plausible observed value nor a compiler accepting a fragment would establish correctness. First check if wrong: mark a separate end boundary after the last element. Revisit M2-L05, “One past is a stopping position” and practice 1.
11 Sum and then update a selected column
Answer A. The selected positions are (0, 1) and (1, 1). At row 0 the program first adds 1, making total = 1, then adds row index 0 to that element, leaving it 1. At row 1 it first adds the current 8, making total = 9, then adds row index 1 to that element, making it 9. The final rows are {4, 1, 6} and {2, 9, 3}. Output: 9 1 9, followed by a newline.
A follows the statement order and both indices. B totals the updated elements, as if the two body statements were reversed; the shown code sums before updating. C traces column 0 instead of the specified column 1, leaving the printed column-1 entries unchanged. D replaces each selected value with r, misreading += r as = r. Other columns are unchanged.
First check if wrong: write every access as a pair (row, column) and record the total before the element update. Revisit M2-L06, the column scan worked example, and M2-L02’s current-state tracing.
12 Keep rows and elements distinct
Answer A and C. grid is an array of two rows, each itself an array of three int elements. In the initializer for row, it supplies a pointer to its first row. row has type int (*)[3], and its one-step movement selects the next whole row. A is true. It does not require a numerical byte size for int.
B is false. The real object contains row arrays, not an array of pointer variables; a pointer to a row is not int **. C is true: for each fixed r, the inner loop finishes all three columns before the outer update changes r. Its fresh c = 0 starts the next row at column 0.
D is false. Row 1 exists, but it has only column indices 0, 1 and 2. Column index 3 supplies no element to read. The total of six integers does not remove the separate row boundary. Do not try to justify an invalid access by treating an int * into one row as a flat traversal of all rows.
First check if wrong: record the type at each level and pair each loop bound with its own dimension. Revisit M2-L06, its nested-loop explanation, row type and row-versus-element stepping sections.
Use your result
The score is a location aid, not a readiness certificate. Pair items 1–2 with M2-L01, 3–4 with M2-L02, 5–6 with M2-L03, 7–8 with M2-L04, 9–10 with M2-L05 and 11–12 with M2-L06. If one answer is wrong, find the first state, target or bound that diverged from the solution, then redo that lesson’s corresponding transfer exercise without looking at its answer. A correct guess is a reason to check the trace too.
This closes the introductory arrays-and-pointers module. It does not complete C, recursion, data structures or GATE CS. Recursion belongs in a later separate module.
Source note
The questions, code, distractors, bilingual explanations and traces are originally authored for this module; they are not reproductions of official examination questions. Language facts were verified against WG14 N1570, including clauses 6.2.4, 6.2.5, 6.3.2.1, 6.5.2.1, 6.5.2.2, 6.5.3.2, 6.5.6, 6.5.13, 6.7.6.3, 6.7.9 and 6.8.5.3. C11 remains a teaching convention.
Notes for this lesson
Sign in to keep your progress. Sign in