CSS Prepare

optional · CSS study notes

II.14 Arrays, Pointers, and Strings

⬆️ P-I.II. Programming Fundamentals · Question Bank · Chapter II (2016–2026)

🧠

Remember: Bounds → address → lifetime → contents.

Start here — what you should be able to do

  • Trace indexing, pointer arithmetic and aliases.
  • Handle C strings and std::string differently.
  • Write replacement, palindrome, allocation and reversal answers with edge cases.

Reading order: foundation checks → full notes and examples → exam traps → self-test without notes → past-paper answers. All sections below remain part of the topic; code examples are kept in full.

Foundation checks

Array and pointer essentials

  • a[i] means *(a + i) only for a valid accessible element.
  • a + n may denote one-past the end; do not dereference it.
  • Arrays often decay to pointers; the array object itself is not a pointer variable.
  • An array parameter such as int a[] is adjusted to a pointer parameter; pass the length separately.
  • Match new with delete, new[] with delete[], and malloc with free.
  • Check n < 2 before forming a last-element pointer for reversal.
  • For 2D arrays, identify row, column and inner-product index separately; matrix multiplication is not elementwise multiplication.
  • Prefer ownership-aware containers in ordinary code; still learn raw pointers for the exam.

1. Arrays

  • A fixed-size, contiguous collection of elements of the same type, accessed by index (0-based in C/C++)
int marks[5] = {90, 85, 78, 92, 88};   // marks[0] = 90 ... marks[4] = 88
  • Size is fixed at declaration — cannot grow/shrink at runtime (unlike dynamic structures)
  • 2D arrays model tables/grids: int matrix[3][4]; — 3 rows, 4 columns, stored row-major in memory (all of row 0, then all of row 1, ...)
  • Accessing an index outside the valid range (marks[10] on a 5-element array) is undefined behavior in C/C++ — no automatic bounds checking

2. Pointers

  • A variable that stores the memory address of another variable
int x = 10;
int *p = &x;    // p now holds the address of x
*p = 20;         // dereference: changes x to 20, via p
  • & — address-of operator, gets a variable's address
  • * — dereference operator, accesses/modifies the value at an address (context-dependent: also used to declare a pointer)
  • Pointer arithmetic: p + 1 advances the pointer by sizeof(type) bytes, not by 1 byte — e.g. on an int*, p+1 moves by sizeof(int), commonly but not necessarily four bytes
  • Pointer to pointer: int **pp = &p; — a pointer that stores the address of another pointer, common in dynamic 2D arrays and passing pointers by reference to functions
  • NULL pointer: a pointer initialized to NULL/nullptr, pointing to nothing — always check before dereferencing to avoid a crash
  • Dangling pointer: a pointer that still holds the address of memory that has been freed/gone out of scope — dereferencing it is undefined behavior

3. Array–Pointer Relationship

  • An array name, in most expressions, decays to a pointer to its first element: marks behaves like &marks[0]
  • marks[i] is equivalent to *(marks + i) — array indexing is really pointer arithmetic in disguise
  • Key difference: sizeof(marks) gives the whole array's size; sizeof(pointer) gives just the pointer's size (e.g. 8 bytes on a 64-bit system) — a classic exam trap
  • A pointer can be reassigned to point elsewhere; an array name cannot be reassigned

4. Strings

  • In C: a null-terminated (\0) character array — "hi" is stored as {'h','i','\0'}, occupying 3 bytes, not 2
  • Common C string functions (from <string.h>): strlen() (length, excluding \0), strcpy() (copy), strcmp() (compare), strcat() (concatenate)
  • In C++: also available as the std::string class, which manages its own memory, supports + for concatenation, == for comparison, and .length()/.size() — safer and easier than raw C strings

5. Common Pitfalls

  • Forgetting the null terminator when manually building a C string
  • Off-by-one errors in loops iterating over arrays (i <= size instead of i < size)
  • Comparing C strings with == (compares addresses, not content) instead of strcmp()
  • Returning a pointer to a local (stack) variable from a function — that memory is invalid once the function returns

6. 💻 Code Examples: C & C++

Arrays, pointer arithmetic, and strings together — including the classic sizeof and string-comparison traps:

C:

#include <stdio.h>
#include <string.h>
int main(void) {
    int marks[5] = {90, 85, 78, 92, 88};
    int *p = marks;                          // array decays to a pointer to marks[0]
    printf("%d %d\n", marks[2], *(p + 2));    // both print 78 -- marks[i] == *(marks+i)

    char str[20] = "hi";                      // 'h','i','\0' -> 3 bytes, not 2
    strcat(str, " there");
    if (strcmp(str, "hi there") == 0)          // NEVER compare C strings with ==
        printf("%s\n", str);

    printf("sizeof(marks)=%zu sizeof(p)=%zu\n", sizeof(marks), sizeof(p));  // different!
    return 0;
}

C++:

#include <iostream>
#include <string>
using namespace std;
int main() {
    int marks[5] = {90, 85, 78, 92, 88};
    int *p = marks;
    cout << marks[2] << " " << *(p + 2) << endl;   // both print 78

    string str = "hi";                        // std::string manages its own memory
    str += " there";
    if (str == "hi there")                      // == compares CONTENT for std::string
        cout << str << endl;

    cout << "sizeof(marks)=" << sizeof(marks)
         << " sizeof(p)=" << sizeof(p) << endl;  // still different -- marks hasn't decayed here
    return 0;
}
  • In C, == on char* strings compares addresses (a bug); in C++, std::string's == is overloaded to compare contents — the exact opposite behavior for what looks like the same operator

7. MCQ Traps

  • Array indexing in C/C++ is 0-based — a 5-element array has valid indices 0 to 4, not 1 to 5
  • sizeof(array) gives total bytes of the array; sizeof(pointer) gives only the pointer's own size — these are not interchangeable even though an array decays to a pointer
  • A C string of "hi" needs 3 bytes of storage, not 2, because of the trailing \0
  • Comparing two C strings with == compares their memory addresses, not their contents — use strcmp() instead
  • Pointer arithmetic scales by the size of the pointed-to type, not by a flat 1 byte

8. Self-Test Questions — with answers

Q1. Why does char str[] = "hi" occupy three characters?

Answer

  • It contains 'h', 'i' and the terminating '\0'.
  • The string length is 2; the array's storage is 3 chars.

Answer

  • marks[i] is equivalent to *(marks + i) for a valid element.
  • Adding i advances i elements, not i bytes.

Q3. What is a dangling pointer?

Answer

  • A pointer to an object whose lifetime has ended or whose storage was released.
  • Dereferencing it is invalid.
  • Nulling one pointer does not repair other aliases; manage ownership and lifetime.

Q4. Why do sizeof(array) and sizeof(pointer) differ?

Answer

  • For an actual array object, sizeof gives all elements' storage.
  • For a pointer, it gives the pointer object's size.
  • An array function parameter is adjusted to a pointer, so sizeof inside that function does not recover the original array length.

Q5. Why use strcmp for C strings?

Answer

  • == on two character pointers compares addresses.
  • strcmp compares the characters and returns a negative, zero or positive value.
  • std::string has its own content-comparison operators.
  1. Why does char str[] = "hi"; require 3 bytes of memory rather than 2?
  2. Explain the relationship between marks[i] and pointer arithmetic on marks.
  3. What is a dangling pointer, and why is dereferencing one dangerous?
  4. Why does sizeof() behave differently on an array versus a pointer to that array's first element?
  5. Why is strcmp() required to compare C-style strings instead of ==?

9. 📝 Exam Practice: Character Replacement in a String

Q: In the following code, replace the character at position pos in string st with character ch. For example, in "hello world", replacing the 2nd character with 'i' would result in "hillo world".

void main()
{
    char st[15]; int pos; char ch;
    int size = 0;
    cin >> pos >> ch;
    while (st[size] != '\0')
    {
        size++;      // calculating length of current string
    }
    // write your code here
}

Solution (completing the skeleton):

#include <iostream>
using namespace std;

void main()
{
    char st[15];
    int pos;
    char ch;
    int size = 0;

    cout << "Enter a string: ";
    cin >> st;

    cout << "Enter position and replacement character: ";
    cin >> pos >> ch;

    while (st[size] != '\0')
    {
        size++;      // calculating length of current string
    }

    // write your code here
    if (pos >= 1 && pos <= size)
    {
        st[pos - 1] = ch;   // pos is 1-indexed, array is 0-indexed
        cout << "Modified string: " << st << endl;
    }
    else
    {
        cout << "Invalid position" << endl;
    }
}

Sample run:

Enter a string: hello
Enter position and replacement character: 2 i
Modified string: hillo

Key reasoning points:

  • pos - 1 converts the question's 1-based counting ("2nd character") into the array's 0-based indexing
  • The while loop manually computes string length by scanning for the '\0' terminator — this is exactly what strlen() does internally; a common CSS angle is "write your own strlen()"
  • void main() is non-standard; modern compilers expect int main() with return 0;
  • Modern C++ equivalent avoids the manual loop entirely: string st; int size = st.length();

Exam angle: examiners may ask you to identify that cin >> st; (reading the actual string) is missing from the skeleton — without it, st holds garbage and the length loop is meaningless.

10. 📜 Past-Paper Questions & MCQs (CSS 2016–2026)

2018 · Paper-I · Q3(f) · 5 marks

Recall cue: Check the position; convert one-based position to zero-based index; replace one character.

Q. Replace the character at position pos in string st with ch (for "helloworld", position 2 and i gives "hilloworld").

Answer — key points

if (pos >= 1 && pos <= size)
    st[pos - 1] = ch;        // positions start at 1, array index at 0
cout << st;

2018 · Paper-I · Q5(a) · 3 marks

Recall cue: Define a pointer to an object whose lifetime has ended; explain causes, undefined behaviour and prevention.

Q. What is a dangling pointer?

Answer — key points

  • A dangling pointer points to memory that has already been freed or has gone out of scope.
  • Causes: using a pointer after delete/free, returning the address of a local variable, or a pointer to a block that has ended.
  • Danger: undefined behaviour, crashes and security holes.
  • Fix: set the pointer to nullptr after deleting it, and do not return addresses of local variables.

2022 · Paper-I · Q2(c) · 6 marks

Recall cue: Draw the array and pointer positions; negative offset is valid only when the resulting element stays inside the array.

Q. Write the output:

int ary[4]={1,2,3,4}; int *p1=ary+3; cout<<p1[-2]<<endl; int *p2=&p1[-2]; *p2=10; cout<<ary[1]<<endl;

Answer — key points

  • p1 points to ary[3], so p1[-2] is ary[1] = 2.
  • p2 points to ary[1], and *p2 = 10 changes it.
  • Output: 2 then 10.

2022 · Paper-I · Q3(c) · 6 marks

Recall cue: Both pointers alias one object; updating through either pointer changes what both observe.

Q. Write the output:

int v1=55; int* p1=&v1; int* p2; p2=p1; *p1=20; cout<<*p2<<endl; cout<<v1<<endl;

Answer — key points

  • p1 and p2 both point to v1. Setting *p1 = 20 changes v1.
  • Output: 20 then 20.

2022 · Paper-I · Q4(a) · 12 marks

Recall cue: Read the line; find its length manually; compare mirrored characters; stop at the first mismatch.

Q. Write a C++ program to check whether a string is a palindrome without string library functions, taking input with cin.getline.

Answer — key points

#include <iostream>
using namespace std;
int main() {
    char s[100];
    cout << "Enter a string: ";
    cin.getline(s, 100);
    int len = 0;
    while (s[len] != '\0') len++;                 // find length manually
    bool pal = true;
    for (int i = 0; i < len / 2; i++)
        if (s[i] != s[len - 1 - i]) { pal = false; break; }
    cout << (pal ? "Palindrome" : "Not a palindrome");
    return 0;
}
  • It compares the first character with the last, the second with the second last, and so on up to the middle.

2023 · Paper-I · Q3(a) · 8 marks

Recall cue: Allocate the requested size; use the array; release with delete[]; prevent leaks and dangling aliases.

Q. How is dynamic memory allocation managed in a C++ program? Clarify with a program.

Answer — key points

  • new allocates memory on the heap at run time and returns its address. delete (or delete[] for arrays) releases it. In C the equivalents are malloc/free.
  • Why: the size is not known at compile time, and the memory lives until it is freed.
  • Risks: memory leaks (forgetting to free), dangling pointers and double deletion.
int n; cin >> n;
int *arr = new int[n];              // allocate
int sum = 0;
for (int i = 0; i < n; i++) { cin >> arr[i]; sum += arr[i]; }
cout << "Sum = " << sum;
delete[] arr;                       // release
arr = nullptr;

2026 · Paper-I · Q3(b) · 6 marks

Recall cue: Define contiguous same-type storage; explain indexed access; describe fixed extent and shifting costs.

Q. What are arrays? Describe one advantage and one limitation.

Answer — key points

  • An array is a fixed-size collection of elements of the same type stored in contiguous memory and accessed by index.
  • Advantage: direct (random) access to any element in O(1) using its index, plus good cache performance.
  • Limitation: its size is fixed when it is created. Insertion or deletion in the middle needs shifting elements (O(n)), and the memory cannot grow without making a new array.

2026 · Paper-I · Q3(c) · 8 marks

Recall cue: Return immediately for fewer than two elements; initialise pointers only then; swap and move inward.

Q. Write pseudocode to reverse an array using pointers.

Answer — key points

if n < 2: return
left  = &arr[0]
right = &arr[n - 1]
while left < right
    temp   = *left
    *left  = *right
    *right = temp
    left   = left + 1
    right  = right - 1
  • Time O(n), extra space O(1).

MCQs

2024 P-I · Q16. Select the correct output of the following code: int arr[5] = {10,20,30,40,50}; printf("%d", arr[5]);

  • (A) Garbage value ✅
  • (B) 20
  • (C) 30
  • (D) None of these
  • Answer: (A) Garbage value.
  • Correct explanation: valid indices are 0–4. Reading arr[5] is undefined behaviour, with no guaranteed output. The stored option “garbage value” is only the source's exam shorthand.

Technical accuracy notes

  • Return immediately when n < 2 before forming the last-element pointer for array reversal.
  • Array bounds must be respected; out-of-bounds access has undefined behaviour, not a predictable output. “Garbage value” in the stored MCQ is an exam shorthand.
  • Setting one freed pointer to nullptr does not fix other aliases that still point to the expired object.
  • Pointer arithmetic must remain within the array or its permitted one-past position. C++ working draft.

Recall check and coverage

  • Explain the three learning outcomes at the top without looking.
  • Reproduce one example or trace and test a boundary case.
  • Answer each self-test, then compare with the key.
  • Attempt each recorded past-paper task on this page.
  • Recorded written references: 2018 · Paper-I · Q3(f) · 5 marks; 2018 · Paper-I · Q5(a) · 3 marks; 2022 · Paper-I · Q2(c) · 6 marks; 2022 · Paper-I · Q3(c) · 6 marks; 2022 · Paper-I · Q4(a) · 12 marks; 2023 · Paper-I · Q3(a) · 8 marks; 2026 · Paper-I · Q3(b) · 6 marks; 2026 · Paper-I · Q3(c) · 8 marks

Evidence limit: this page preserves the question records found in your Notion notes. Disputed labels and questions not checked against original PDFs remain flagged in the Question Bank; this is not a claim of exhaustive original-paper verification.