C-Style Arrays and Dynamic Arrays, CSCE 120 Exam 3 – Study Notes
offline

Difficulty: Beginner to Intermediate | Prerequisites: Basic C++ syntax, pointers, loops


Big Picture

Arrays are one of the first data structures you encounter, and in C++ you need to understand two flavours: fixed-size C-style arrays that live on the stack, and dynamic arrays allocated on the heap with new. This material underpins everything that follows in CSCE 120 about memory management, vectors, and the Rule of Three. If you are comfortable with pointer arithmetic and know exactly when memory is allocated and freed, the rest of the exam topics fall into place. You should already be comfortable with basic pointer syntax (*, &) before diving in.


TL;DR

C-style arrays are fixed-size, stack-allocated, and cannot be copied with =. Dynamic arrays use new[] and delete[] to allocate and free heap memory at runtime. Every new must have a matching delete, and you must track size yourself since dynamic arrays carry no built-in length information.


Key Terms

C-style array

A fixed-size, contiguous block of memory declared with a compile-time constant size (e.g. int arr[5]). Lives on the stack. Think of it as a row of boxes whose count is locked in at compile time.

Dynamic array

A contiguous block of memory allocated at runtime on the heap using new[]. The programmer controls its lifetime and must free it with delete[]. In simple terms, this is an array whose size you decide while the programme is running.

Heap (free store)

The region of memory used for dynamic allocation. Objects placed here persist until explicitly freed. Think of it as long-term storage you rent and must return yourself.

Stack

Memory that is automatically managed per function call. Local variables (including C-style arrays) live here and are cleaned up when the function returns.

Uninitialised memory (garbage)

Memory that has been allocated but not set to a known value. Reading it is undefined behaviour. In simple terms, the bytes contain whatever happened to be there before, which is meaningless to your programme.

delete[]

The operator used to free a dynamically allocated array. Using plain delete on an array, or delete[] on a single object, is undefined behaviour.


Core Content

C-Style Array Declaration and Initialisation

  • int arr[5]; declares an array of 5 integers whose contents are uninitialised garbage.

  • int arr[5] = {1, 2, 3, 4, 5}; initialises all five elements.

  • int arr[5] = {1, 2}; sets the first two elements; the remaining three are zero-initialised.

  • int arr[] = {4, 5, 6}; lets the compiler infer the size (3 in this case).

  • int a[3], b[3]; a = b; is a compiler error. You cannot copy a C-style array with assignment. You must copy element by element.

Dynamic Array: Declare, Allocate, Initialise

The three-step pattern to remember:

  • Declare a pointer: int* arr;

  • Allocate on the heap: arr = new int[size];

  • Initialise the elements: loop through and assign values.

Three allocation forms and what they give you:

  • new int[n] allocates space but leaves it full of garbage. Reading before writing is undefined behaviour.

  • new int[n]() allocates and zero-initialises every element.

  • new int[3]{1,2,3} allocates and initialises to the given values.

Accessing and Traversing

Indexing and traversal work identically for C-style and dynamic arrays. arr[i] gives you the element at position i. A standard for loop from 0 to size - 1 covers every element.

Doubling Capacity

A common growth strategy: allocate a new array twice the current capacity, copy old elements, fill new slots with a default, delete the old array, and redirect the pointer.

void double_capacity(int*& array, int& capacity) {
    int* newArr = new int[capacity * 2]();
    for (int i = 0; i < capacity; i++)
        newArr[i] = array[i];
    for (int i = capacity; i < 2 * capacity; i++)
        newArr[i] = array[0] + i;   // or any default
    delete[] array;
    array = newArr;
    capacity = capacity * 2;
}

The pointer is passed by reference (int*&) so the caller's pointer is updated to the new memory.

Inserting Into a Dynamic Array

To insert a value at index i:

  • Allocate a new array one element larger.

  • Copy elements before index i as-is.

  • Place the new value at index i.

  • Copy elements after index i, each shifted one position right.

  • Delete the old array, redirect the pointer, increment size.

void insert(int*& arr, int& size, int value, int index) {
    int* newArr = new int[size + 1];
    for (int i = 0; i < index; i++)
        newArr[i] = arr[i];
    newArr[index] = value;
    for (int i = index; i < size; i++)
        newArr[i + 1] = arr[i];
    delete[] arr;
    arr = newArr;
    size++;
}

Removing From a Dynamic Array

To remove the element at index i:

  • Allocate a new array one element smaller.

  • Copy elements before i.

  • Copy elements after i, each shifted one position left.

  • Delete the old array, redirect the pointer, decrement size.

void removeAt(int*& arr, int& size, int index) {
    int* newArr = new int[size - 1];
    for (int i = 0; i < index; i++)
        newArr[i] = arr[i];
    for (int i = index + 1; i < size; i++)
        newArr[i - 1] = arr[i];
    delete[] arr;
    arr = newArr;
    size--;
}

Resizing a Dynamic Array (Grow or Shrink)

A general-purpose resize copies the overlapping portion and zero-initialises any new slots:

void resize(int*& arr, int oldSize, int newSize) {
    int* newArr = new int[newSize];
    int minSize = (oldSize < newSize) ? oldSize : newSize;
    for (int i = 0; i < minSize; i++)
        newArr[i] = arr[i];
    for (int i = minSize; i < newSize; i++)
        newArr[i] = 0;
    delete[] arr;
    arr = newArr;
}

Properly Destroying a Dynamic Array

Freeing memory is not enough on its own. You must also prevent dangling pointers:

void destroy(int*& arr, int& size) {
    delete[] arr;
    arr = nullptr;
    size = 0;
}

Linear Search

A straightforward scan returning the index of the target, or -1 if not found:

int find(int* arr, int size, int target) {
    for (int i = 0; i < size; i++)
        if (arr[i] == target) return i;
    return -1;
}

Formulas / Diagrams

No mathematical formulas for this section. The key "diagram" to hold in your head: a pointer variable on the stack holds the address of the first element of a contiguous block on the heap. Inserting or removing means creating a whole new block, copying, and deleting the old one.


Real-World Applications

Dynamic arrays are the backbone of std::vector in C++. Every time a vector grows beyond its capacity, it performs exactly this allocate-copy-delete cycle behind the scenes. Understanding it manually is how you understand what the standard library is doing for you.


Common Misconceptions

  • "I can copy a C-style array with =." You cannot. a = b on two arrays is a compiler error. You must loop and copy element by element.

  • "new int[n] gives me zeros." It does not. Without the parentheses (), the memory is uninitialised. Reading it is undefined behaviour.

  • "I only need delete, not delete[], for arrays." Using delete instead of delete[] on an array is undefined behaviour. Always match new[] with delete[].

  • "After delete[] arr, I can still safely read arr[0]." No. The memory has been freed. Accessing it is undefined behaviour (dangling pointer).


Why It Matters / Exam Flags

  • ⚠️ Know the difference between new int[n], new int[n](), and new int[n]{...}. This is a common multiple-choice trap.

  • ⚠️ Every insert/remove function must allocate a new array, copy, and delete the old one. Forgetting delete[] is a memory leak. Forgetting to update the pointer is a dangling pointer.

  • ⚠️ Passing the pointer by reference (int*&) is essential when the function needs to change which memory the caller's pointer points to.

  • ⚠️ The ternary operator condition ? expr_true : expr_false appears in resize logic. Know its syntax.


Quick Self-Test

  1. True or False: int arr[5] = {1, 2}; leaves elements arr[2], arr[3], and arr[4] as garbage.

  1. Fill in the blank: To free a dynamically allocated array, use ________.

  1. True or False: new int[10] zero-initialises all elements.

  1. Fill in the blank: After delete[] arr;, you should set arr = ________ to avoid a dangling pointer.

  1. True or False: You can assign one C-style array to another with a = b;.

Answers: 1. False (they are zero-initialised). 2. delete[]. 3. False (use new int[10]() for zeros). 4. nullptr. 5. False (compiler error).


Practice Q&A

Q: What is the output of the following code?

int* arr = new int[3]{10, 20, 30};
int* newArr = new int[5]();
for (int i = 0; i < 3; i++) newArr[i] = arr[i];
delete[] arr;
arr = newArr;
cout << arr[3];

A: 0. The new array was zero-initialised with (), and only indices 0-2 were overwritten.

Q: Why must arr be passed as int*& (reference to pointer) in an insert function?

A: Because the function allocates a new array and needs the caller's pointer to point to the new memory. Without the reference, only a local copy of the pointer would be updated, and the caller would still point to the (now deleted) old array.

Q: Write code to remove the element at index 2 from a dynamic array of size 5, then print the resulting array.

A: Allocate a new array of size 4, copy elements at indices 0 and 1 directly, copy elements at indices 3 and 4 shifted left by one, delete the old array, update the pointer and size, then loop and print.

Q: What happens if you write delete arr; instead of delete[] arr; for a dynamically allocated array?

A: Undefined behaviour. Only the first element may be properly destroyed, and the runtime's bookkeeping for the array allocation is corrupted.


Connections to Other Topics

This material connects directly to dynamic memory management (Part 2 of these notes), where you will learn about memory leaks, dangling pointers, and RAII. It also connects to the tiny vector / std::vector topic (Part 3), which wraps exactly these operations inside a class with automatic capacity management.


Related Terms / Search Tags

C-style array, static array, dynamic array, heap allocation, stack allocation, new[], delete[], pointer to array, array resize, array insert, array remove, linear search, uninitialised memory, garbage values, zero-initialisation, value-initialisation, CSCE 120, Texas A&M, Exam 3