Arrays and Strings
Arrays keep a fixed, ordered collection of values together. C strings use the same idea—an ordered character array—with one extra rule: a null character marks where the text ends. Learn the rules that make both useful instead of dangerous.
One contiguous collection, one explicit valid range
\0 and use the string tools that respect that terminator.An array has a type, a capacity, and zero-based positions
int temperatures[5]; reserves five adjacent int elements. Its declared capacity is five, but the legal indexes are 0 through 4. The bracket expression selects one element: temperatures[0] is the first element and temperatures[4] is the fifth.
There is no automatic bounds check in ordinary C. temperatures[5] does not refer to a sixth element; it attempts to access memory outside the object. That is undefined behavior. It may seem to work, produce a surprising value, damage another variable, or fail later. Write the bound once, name it, and use it consistently.
The declared space in int values[5].
The first element is always selected with zero.
For a count of five, last valid index is count - 1.
values[count] is already outside the array.
Initialize the values you mean to have
An initializer list makes the first values explicit: int scores[5] = {16, 19, 14, 20, 18};. If the list is shorter than the declared capacity, the remaining elements are initialized to zero. This is useful for an all-zero array: int counters[12] = {0};.
The array capacity is separate from a runtime count. An array may have room for twelve results while a variable used says that only seven currently hold meaningful data. When that happens, loops should use used, not the full capacity.
Read every numeric element inside its valid range
The loop visits indexes 0 through 4, adds each temperature once, and then reads the last element with count - 1.
Edit the program, predict its output, then run it.
Use index < count, never index <= count
For a sequence with count usable elements, the correct full traversal is for (int index = 0; index < count; index++). The first iteration uses index zero. The final iteration uses count - 1. Then the increment makes index equal to count, and the condition becomes false before an invalid access occurs.
Repair an out-of-bounds loop
The runner reports the invalid array index instead of silently masking it. Replace <= with <, then rerun.
Edit the program, predict its output, then run it.
Aggregate data without losing the type rule
A common pattern uses an accumulator initialized before the loop: int total = 0;. Each iteration updates it with one element. For a fractional average, ensure that one side of division is a double: double average = total / 5.0;. If both operands are int, C integer division discards any fractional part before the result is stored.
Keep the number of meaningful elements in one variable or a named constant. It is the loop's contract.
Use the mathematical identity for the operation: zero for a sum, one for a product, or a carefully chosen first element for a minimum.
Use values[index] only while the condition proves index is inside the valid range.
Use %d for an int total and %f for a double average.
A function receives an array address, not its original length
When an array is passed to a function, the parameter acts like a pointer to its first element. The function can access elements, but it cannot reliably discover how many elements the caller created. Pass the count explicitly and preserve the same boundary contract inside the function.
int sum_scores(const int scores[], int count) {
int total = 0;
for (int index = 0; index < count; index++) {
total += scores[index];
}
return total;
}The const in const int scores[] documents that this function only reads the array. It protects callers from accidental element assignments inside the function. The array notation in the parameter improves readability, but the count is still required.
A C string is a character array terminated by \0
char city[16] = "Rabat"; creates a writable character array. The visible letters occupy positions 0 through 4; C places a terminating null character \0 at position 5. String-aware functions use that marker to know where text ends.
Capacity must include both the visible characters and the terminator. char city[6] = "Rabat"; fits exactly. char city[5] = "Rabat"; does not leave room for \0 and is invalid. A larger buffer is often intentional when you will later read or build longer text.
Print a full string and one selected character
The char array stores text for %s, while city[0] selects exactly one character for %c.
Edit the program, predict its output, then run it.
Read and compare text with a capacity-aware policy
scanf("%s", city) is unsafe for a fixed buffer because it has no limit. For a char city[16] that reads one whitespace-delimited word, use a field width: scanf("%15s", city);. The width leaves one slot for \0. It stops at whitespace, so it is not suitable for a full city name with spaces.
For a line of text, prefer fgets(city, sizeof city, stdin). It receives the buffer and its capacity, and it can retain spaces. It may keep a trailing newline when there is room, so real programs often remove that newline deliberately before comparison or display.
strlen counts visible characters before \0.#include <string.h>It does not know the array's total capacity, so only use it with a properly terminated string.strcmp(a, b) == 0 for equal text.if (strcmp(city, "Rabat") == 0) { ... }== compares addresses for character arrays and pointers, not the sequence of characters.fgets(city, sizeof city, stdin);Check its return value in production code, then decide whether a retained newline should be removed.Do not write through a pointer to a string literal
char city[] = "Rabat"; creates an array you can modify. By contrast, char *city = "Rabat"; points at a string literal. Treat that literal as read-only: assigning city[0] = 'r'; has undefined behavior. Use a character array whenever the program must change the characters.
Independent lab: publish a compact score report
Run the starter first. Then extend it without breaking the two boundaries: only access indexes from zero through count - 1, and only store text that fits inside report_name with its terminator. This browser runner covers the fixed-size declarations and indexed calculations; compile locally for function and input-library experiments.
Calculate and label a score report
A numeric array produces the total and average, while a character array supplies a safe report label.
Edit the program, predict its output, then run it.
highest from scores[0], then compare every later score through a bounded loop.passed and increment it when scores[index] >= 16.int sum_scores(const int scores[], int count).fgets, using sizeof report_name and checking the result.Lesson review
- A declared array capacity of
counthas valid indexes from0throughcount - 1. - A full traversal uses
index < count;index <= countaccesses one element too far. - Array out-of-bounds access is undefined behavior. C does not repair or safely clamp it.
- Pass an array's meaningful element count to every function that needs to process it.
- A C string is a character sequence ending in
\0, so capacity must include one extra character. %sprints a complete terminated string;%cprints one character.- Use field widths with
scanfand preferfgetsfor capacity-aware line input. - Use
strcmpto compare string contents, and write only into actual character arrays—not literals.