When the array length is known only at runtime
Suppose we are writing a program to summarize student scores. While writing the code, we do not know whether this run will have 3 students or 30. We learn the required number of elements only after the program starts and the user enters the class size.
The earlier declaration int numbers[4]; reserves four integer positions in advance. A much larger constant may waste space and still imposes a capacity limit. Instead, we want to learn the actual count first and then reserve enough storage.
This is dynamic memory allocation: request an appropriately sized region when the running program needs it, and return it when finished. “Dynamic” means the allocation time and size can be decided at runtime, not that the array automatically grows.
An array region and a pointer holding its address
Think of memory as many addressable cells. Allocating an array requests consecutive cells for its elements. A successful allocation gives us the first cell's address; it does not put the entire array inside a pointer variable.
numbers holds the region's starting address, while expressions such as numbers[0] and numbers[1] access its elements through that address. The pointer variable and its array occupy separate storage. The region used for such explicitly allocated storage is commonly called the heap.
In C, malloc comes from <stdlib.h> and takes a size in bytes. length * sizeof(*numbers) means “element count × size of one integer.” Here, sizeof(*numbers) obtains the type's size without reading through the pointer. Allocation failure returns NULL; check the result before using the array.
These newly allocated integers are not initialized yet. They cannot be read as if scores had already been entered. Write every element before calculating with it.
Example: enter the count, then the scores
This program first reads the student count, restricts this example to 1–1000 students, and allocates an array of that length. It then reads each score and calculates the average. Both normal completion and invalid score input release the allocated storage.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int length;
printf("Number of students (1-1000): ");
if (scanf("%d", &length) != 1 || length < 1 || length > 1000) {
fprintf(stderr, "Invalid number of students.\n");
return 1;
}
int *numbers = malloc((size_t) length * sizeof(*numbers));
if (numbers == NULL) {
fprintf(stderr, "Not enough memory.\n");
return 1;
}
for (int i = 0; i < length; i++) {
printf("Score %d: ", i + 1);
if (scanf("%d", &numbers[i]) != 1 || numbers[i] < 0 || numbers[i] > 100) {
fprintf(stderr, "Invalid score.\n");
free(numbers);
numbers = NULL;
return 1;
}
}
double total = 0;
for (int i = 0; i < length; i++) {
total += numbers[i];
}
printf("Average: %.1f\n", total / length);
free(numbers);
numbers = NULL;
return 0;
}KNOWLEDGE QUIZ
Create a score array at runtime
Unlock the complete interactive lab, deeper explanations, and curated reference answers.
KNOWLEDGE QUIZ
Finish using the data: release storage, then clear the pointer
free(numbers); returns the dynamic array's storage; it does not remove the local variable numbers. After release, do not read or modify those elements or release the same region again.
Releasing storage does not assign a null pointer to numbers for you. Follow it with numbers = NULL; to show that it no longer points to a usable array. Any other pointer to the same region also becomes unusable; clearing numbers does not repair other pointers.
The length remains fixed for this allocation. To handle another group, finish using and release the old array, then allocate again using the new input. Restart the lab with a different count and compare the number of cells created.
KNOWLEDGE QUIZ
Build a square-number array
Implement int *make_squares(int length) to dynamically create length integers containing 1² through length²; return NULL on failure. In main, print five values and free the memory.
- Validate that n is positive.
- Allocate n integers and check the result.
- Fill and print square values, then release storage and clear the pointer.
Copy an integer array
Implement int *copy_array(const int *source, int length), allocate a new array, and copy each item. Test with {3, 1, 4, 1}, print the copy, and free it.
- Allocate the destination using the element count.
- Copy each integer rather than copying only the pointer.
- Edit one copied element, print both arrays, and release the destination.