Arrays#

Defining and initializing an array#

#include <stdio.h>

#define QUEUE_SIZE 4
#define STR_SIZE 50
#define MEALS_PER_DAY 4

int queue[QUEUE_SIZE];
// `queue` is an array of `QUEUE_SIZE` integers.
// Its size is *explicit*.

char input[] = "N/A";
// `input` is an array of 4 chars (string).
// Its size is *implicit*.

const char VERSION[] = "0.2.1-2025-09-17";
// `const` makes each character read-only, so we cannot accidentally change it
// in our code.
// So, `VERSION` is an array of `_Countof("...")` read-only characters.

const int prime_numbers[] = {2, 3, 5, 7, 11, 13}; // Array size implicit

const char ROBOT_NAMES_SPACIOUS[][STR_SIZE] = {"HAL 9000", "R2-D2", "WALL-E"};
// Array of const char[STR_SIZE]
// For each string we reserve `STR_SIZE` space, which does not make sense for
// constant strings. You waste space.

const char *const ROBOT_NAMES[] = {"HAL 9000", "R2-D2", "WALL-E"};
// Array of const char * (address).
// Using pointers saves space.

double caloriesEachDayEachMeal[][MEALS_PER_DAY] = {
    {350.0, 620.5, 800.0},        // First day (breakfast, lunch, dinner)
    {300.0, 590.0, 620.3, 200.6}, // Second day (+ night snack)
    {940.2, 790.5}                // etc
};

int main() {
  // What happens when you try these?
  // ROBOT_NAMES[0] = "Robocop";
  // ROBOT_NAMES = ROBOT_NAMES_SPACIOUS;

  // Repeating the same operation on an array
  puts("Prime numbers:");
  for (size_t i = 0; // Use size_t if sizeof is used
       i < _Countof prime_numbers; ++i)
    printf("%lu: %2d\n", // %lu, because sizeof is a long unsigned
           i, prime_numbers[i]);

  puts("Size of robot name arrays:");
  printf("ROBOT_NAMES_SPACIOUS: %lu\n", sizeof ROBOT_NAMES_SPACIOUS);
  printf("ROBOT_NAMES: %lu\n", sizeof ROBOT_NAMES);
  puts("");
  puts("Robot names:");
  for (size_t i = 0; i < _Countof ROBOT_NAMES; ++i) {
    puts(ROBOT_NAMES_SPACIOUS[i]);
    puts(ROBOT_NAMES[i]);
  }
  puts("");
}
Output
Prime numbers:
0:  2
1:  3
2:  5
3:  7
4: 11
5: 13
Size of robot name arrays:
ROBOT_NAMES_SPACIOUS: 150
ROBOT_NAMES: 24

Robot names:
HAL 9000
HAL 9000
R2-D2
R2-D2
WALL-E
WALL-E
Array (data structure)

A data structure consisting of a collection of elements (values or variables), of same memory size, each identified by at least one array index or key.

Activity 13

Which of the following correctly define and/or initialize an array?

  1. int array[];

  2. int array;

  3. char[] choices = {"black bird", "great tit", "falcon"};

  4. char names[] = {"ird", "grea", "con"};

  5. int part_ids[]= {3093, -49318, 3092.812};

  6. string names[] = [];

  7. double intensity[X][Y][Z];

Activity 14

Visualize the memory layout of robot_names_v* using the debugger:

  1. set a breakpoint on the first line of main().

  2. F5

  3. On the left click on Variables => Global.

  4. Hover on a variable and click on the icon .

  5. You will be asked if you want to install Hex Editor. Install it.

  6. memory.bin file will be opened.

Answer the questions:

  1. Localize both robot_names_v*.

  2. What is the difference in their memory layout?

sizeof and _Countof operators#

sizeof operator returns the size of an object in bytes.

_Countof operator returns the size of an array. It is similar to:

#define _Countof(arr) (sizeof(arr) / sizeof((arr)[0]))

size_t datatype#

If you use the output of a sizeof or _Countof operator in a loop, then use size_t – for example in a for loop.

for loop statement#

Used to repeat an operation over every element of an array. This is also called iterating over an array.

for (
    initialize;
    check_before_each_repetition;
    do_after_the_repetition
    ) {
    operations;
}

You can also nest for loops:

#include <stddef.h>
#include <stdio.h>

#define COURSE_COUNT 2
#define STUDENT_COUNT 2
#define GRADE_COUNT 3

unsigned scores[COURSE_COUNT][STUDENT_COUNT][GRADE_COUNT] = {
    // Course 1
    {
        {10, 12, 9}, // Student 1
        {3, 5, 0},   // Student 2
    },
    // Course 2
    {
        {10, 12, 9},
        {0, 3, 12},
    }};

int main() {
  // Repeating the same operation on an array
  puts("Student scores:");
  for (size_t c = 0; c < _Countof scores; ++c)
    for (size_t s = 0; s < _Countof scores[c]; ++s)
      for (size_t g = 0; g < _Countof scores[c][s]; ++g)
        printf("%lu: %2u\n", g, scores[c][s][g]);
}
Output
Student scores:
0: 10
1: 12
2:  9
0:  3
1:  5
2:  0
0: 10
1: 12
2:  9
0:  0
1:  3
2: 12

Activity 15

Write a for loop for caloriesEachDayEachMeal above with the following requirements:

  • prints all the data in the array.

  • Each data should be in its own row.

  • uses _Countof.

Useful operations#

Searching for an element and modifying an element

#include <stdio.h>
#include <stdlib.h>

int ids[] = {5, 2, 9, 1};

int main() {
  // Search for number
  int searched_number;
  printf("Which are you searching for? ");
  scanf("%d", &searched_number);

  bool number_found = false;
  for (size_t i = 0; i < _Countof ids; ++i)
    if (ids[i] == searched_number) {
      printf("Found number %d at index %lu", searched_number, i);
      number_found = true;
    }
  if (!number_found)
    puts("Number not found.");

  // Modifying an element of an array
  ids[0] = -1;
  for (size_t i = 0; i < _Countof ids; ++i)
    printf("%2lu: %3d\n", i, ids[i]);
}