Help improve SovranCode?

Google Analytics can measure anonymous usage after you choose Allow. Essential account and progress features work either way.

SovranCode
C: Foundations for Systems Programming Arrays and Strings
This device
Course contentsArrays and Strings · 15 titles

C foundations

What C Is and How C Programs RunYour First C ProgramVariables, Types, and OperatorsInput and Output with printf and scanfConditions and Loops

Program structure and data

Functions, Headers, and ScopeArrays and StringsPointers and Memory AddressesStructures, Enumerations, and UnionsFiles and Command-Line Arguments

Memory, tooling, and practice

Dynamic Memory AllocationPreprocessor Directives and Separate CompilationErrors, Debugging, and Undefined BehaviorBuild Tools and MakefilesProject: Command-Line Inventory Manager
C: Foundations for Systems Programming15 complete lessons

C foundations

What C Is and How C Programs RunYour First C ProgramVariables, Types, and OperatorsInput and Output with printf and scanfConditions and Loops

Program structure and data

Functions, Headers, and ScopeArrays and StringsPointers and Memory AddressesStructures, Enumerations, and UnionsFiles and Command-Line Arguments

Memory, tooling, and practice

Dynamic Memory AllocationPreprocessor Directives and Separate CompilationErrors, Debugging, and Undefined BehaviorBuild Tools and MakefilesProject: Command-Line Inventory Manager
PREVIOUS LESSONFunctions, Headers, and Scope
NEXT LESSONPointers and Memory Addresses
Program structure and data 135 min

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.

What you will leave with

You will be able to declare and initialize numeric arrays, trace their zero-based indexes, choose a correct loop boundary, calculate totals and averages, explain why functions need an array length, create safely sized character strings, use %s and %c, and recognize the source of common capacity bugs.

One contiguous collection, one explicit valid range

Model ordered dataKeep related readings, scores, or flags in a fixed-size array instead of inventing unrelated variable names.
Visit exactly onceStart at index zero and stop before the element count so every read and write stays inside the array.
Protect capacityTreat an out-of-bounds access as a defect, not a value C will safely correct for you.
Represent text accuratelyReserve one extra character for \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.

capacity5 elements

The declared space in int values[5].

first index0

The first element is always selected with zero.

last index4

For a count of five, last valid index is count - 1.

first invalid5

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.

C FUNDAMENTALS RUNNER

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.

#include <stdio.h>

int main(void) {
  int temperatures[5] = {18, 21, 15, 20, 19};
  int count = 5;
  int total = 0;

  for (int index = 0; index < count; index++) {
    total = total + temperatures[index];
  }

  printf("Total: %d\n", total);
  printf("Last reading: %d\n", temperatures[count - 1]);
  return 0;
}
TERMINAL OUTPUT
Edit the program, predict its output, then run it.

This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

Try this next: Change one reading, run it, then add temperatures[2] = 17; before the loop. Keep the index in range and predict the new total.

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.

The familiar off-by-one bug

index <= count permits one extra iteration at index == count. It is not a harmless way to include the final element; the final valid element was already count - 1. Repair the program below by changing only the comparison.

C FUNDAMENTALS RUNNER

Repair an out-of-bounds loop

The runner reports the invalid array index instead of silently masking it. Replace <= with <, then rerun.

#include <stdio.h>

int main(void) {
  int scores[4] = {14, 18, 16, 20};
  int count = 4;
  int total = 0;

  for (int index = 0; index <= count; index++) {
    total = total + scores[index];
  }

  printf("Total: %d\n", total);
  return 0;
}
TERMINAL OUTPUT
Edit the program, predict its output, then run it.

This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

Try this next: After the repair, change count to 3 and explain which scores are intentionally included. Then restore count to 4 for the full report.

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.

  • 01
    Decide the valid count

    Keep the number of meaningful elements in one variable or a named constant. It is the loop's contract.

  • 02
    Set the accumulator

    Use the mathematical identity for the operation: zero for a sum, one for a product, or a carefully chosen first element for a minimum.

  • 03
    Read one indexed value

    Use values[index] only while the condition proves index is inside the valid range.

  • 04
    Report with the intended type

    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.

    C FUNDAMENTALS RUNNER

    Print a full string and one selected character

    The char array stores text for %s, while city[0] selects exactly one character for %c.

    #include <stdio.h>
    
    int main(void) {
      char city[16] = "Rabat";
    
      printf("City: %s\n", city);
      printf("First character: %c\n", city[0]);
      return 0;
    }
    TERMINAL OUTPUT
    Edit the program, predict its output, then run it.

    This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

    Try this next: Change Rabat to a city with at most 15 visible characters. Then try city[1] and explain why the final visible index is length - 1.

    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.

    String lengthstrlen 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.
    String comparisonUse strcmp(a, b) == 0 for equal text.if (strcmp(city, "Rabat") == 0) { ... }== compares addresses for character arrays and pointers, not the sequence of characters.
    Safe line inputPass capacity to the input routine.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.

    Make capacity visible at the declaration

    When a buffer has a known purpose, choose a named size or use sizeof buffer at the call that needs capacity. Avoid a separate magic number that can drift away from the actual array declaration.

    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.

    C FUNDAMENTALS RUNNER

    Calculate and label a score report

    A numeric array produces the total and average, while a character array supplies a safe report label.

    #include <stdio.h>
    
    int main(void) {
      char report_name[24] = "Practice results";
      int scores[5] = {16, 19, 14, 20, 18};
      int count = 5;
      int total = 0;
    
      for (int index = 0; index < count; index++) {
        total = total + scores[index];
      }
    
      double average = total / 5.0;
      printf("%s\n", report_name);
      printf("Total: %d\n", total);
      printf("Average: %f\n", average);
      return 0;
    }
    TERMINAL OUTPUT
    Edit the program, predict its output, then run it.

    This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

    Try this next: Replace the five scores, add a sixth score by enlarging the array and count, and update the divisor to 6.0. Then rename the report without exceeding 23 visible characters.

    01Find a maximumInitialize highest from scores[0], then compare every later score through a bounded loop.
    02Count a conditionAdd passed and increment it when scores[index] >= 16.
    03Design a functionIn a local compiler, move the total loop into int sum_scores(const int scores[], int count).
    04Accept a line safelyReplace the fixed label with fgets, using sizeof report_name and checking the result.

    Lesson review

    • A declared array capacity of count has valid indexes from 0 through count - 1.
    • A full traversal uses index < count; index <= count accesses 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.
    • %s prints a complete terminated string; %c prints one character.
    • Use field widths with scanf and prefer fgets for capacity-aware line input.
    • Use strcmp to compare string contents, and write only into actual character arrays—not literals.
    KNOWLEDGE CHECK

    Protect every element and every terminator

    Answer from the program's memory contract: a numeric array has a fixed valid range, and a character string needs room for a final null character. Read every explanation before moving on.

    01What are the valid indexes for int scores[5]?
    02Why is for (int index = 0; index < count; index++) the usual full-array loop boundary?
    03What happens if a real C program reads scores[5] from int scores[5]?
    04What does an initializer leave in the final two positions of int flags[4] = {1, 1};?
    05Which declaration has enough storage for the string "Rabat"?
    06What marks the end of an ordinary C string stored in a char array?
    07Which printf placeholder prints a full null-terminated character string?
    08What does strlen(city) count for a properly terminated string?
    09Why should a function that processes an array normally receive a count parameter too?
    10Which input call protects a 16-character city buffer from a longer whitespace-delimited word?
    PREVIOUS LESSONFunctions, Headers, and Scope
    NEXT LESSONPointers and Memory Addresses
    ON THIS PAGEArrays and StringsLesson mapArray modelInitializersLoop boundariesCalculationsArrays in functionsString modelString inputString literalsIndependent labLesson reviewKnowledge check
    Course contents