10.2 — Arrays (Part II)

This lesson continues the discussion of arrays that began in lesson 10.1 -- Arrays (Part I).

Initializing fixed arrays

Array elements are treated just like normal variables, and as such, they are not initialized when created.

One way to “initialize” an array is to do it element by element:

However, this is a pain, especially as the array gets larger. Furthermore, it’s not initialization, but assignment. Assignments don’t work if the array is const.

Fortunately, C++ provides a more convenient way to initialize entire arrays via use of an initializer list. The following example initializes the array with the same values as the one above:

If there are more initializers in the list than the array can hold, the compiler will generate an error.

However, if there are less initializers in the list than the array can hold, the remaining elements are initialized to 0 (or whatever value 0 converts to for a non-integral fundamental type -- e.g. 0.0 for double). This is called zero initialization.

The following example shows this in action:

This prints:


Consequently, to initialize all the elements of an array to 0, you can do this:

If the initializer list is omitted, the elements are uninitialized, unless they are a class-type.

Best practice

Explicitly initialize arrays, even if they would be initialized without an initializer list.

Omitted length

If you are initializing a fixed array of elements using an initializer list, the compiler can figure out the length of the array for you, and you can omit explicitly declaring the length of the array.

The following two lines are equivalent:

This not only saves typing, it also means you don’t have to update the array length if you add or remove elements later.

Arrays and enums

One of the big documentation problems with arrays is that integer indices do not provide any information to the programmer about the meaning of the index. Consider a class of 5 students:

Who is represented by testScores[2]? It’s not clear.

This can be solved by setting up an enumeration where one enumerator maps to each of the possible array indices:

In this way, it’s much clearer what each of the array elements represents. Note that an extra enumerator named max_students has been added. This enumerator is used during the array declaration to ensure the array has the proper length (as the array length should be one greater than the largest index). This is useful both for documentation purposes, and because the array will automatically be resized if another enumerator is added:

Note that this “trick” only works if you do not change the enumerator values manually!

Arrays and enum classes

Enum classes don’t have an implicit conversion to integer, so if you try the following:

You’ll get a compiler error. This can be addressed by using a static_cast to convert the enumerator to an integer:

However, doing this is somewhat of a pain, so it might be better to use a standard enum inside of a namespace:

Passing arrays to functions

Although passing an array to a function at first glance looks just like passing a normal variable, underneath the hood, C++ treats arrays differently.

When a normal variable is passed by value, C++ copies the value of the argument into the function parameter. Because the parameter is a copy, changing the value of the parameter does not change the value of the original argument.

However, because copying large arrays can be very expensive, C++ does not copy an array when an array is passed into a function. Instead, the actual array is passed. This has the side effect of allowing functions to directly change the value of array elements!

The following example illustrates this concept:

before passValue: 1
after passValue: 1
before passArray: 2 3 5 7 11
after passArray: 11 7 5 3 2

In the above example, value is not changed in main() because the parameter value in function passValue() was a copy of variable value in function main(), not the actual variable. However, because the parameter array in function passArray() is the actual array, passArray() is able to directly change the value of the elements!

Why this happens is related to the way arrays are implemented in C++, a topic we’ll revisit once we’ve covered pointers. For now, you can consider this as a quirk of the language.

As a side note, if you want to ensure a function does not modify the array elements passed into it, you can make the array const:

Determining the length of an array

The std::size() function from the <iterator> header can be used to determine the length of arrays.

Here’s an example:

This prints:

The array has: 8 elements

Note that due to the way C++ passes arrays to functions, this will not work for arrays that have been passed to functions!

std::size() will work with other kinds of objects (such as std::array and std::vector), and it will cause a compiler error if you try to use it on a fixed array that has been passed to a function! Note that std::size returns an unsigned value. If you need a signed value, you can either cast the result or, since C++20, use std::ssize() (Stands for signed size).

std::size() was added in C++17. If you’re still using an old compiler, you have to use the sizeof operator instead. sizeof isn’t as easy to use as std::size() and there are a few things you have to watch out for. If you’re using a C++17-capable compiler, you can skip to section “Indexing an array out of range”.

The sizeof operator can be used on arrays, and it will return the total size of the array (array length multiplied by element size).

On a machine with 4 byte integers and 8 byte pointers, this printed:


(You may get a different result if the size of your types are different).

One neat trick: we can determine the length of a fixed array by dividing the size of the entire array by the size of an array element:

This printed

The array has: 8 elements

How does this work? First, note that the size of the entire array is equal to the array’s length multiplied by the size of an element. Put more compactly: array size = array length * element size.

Using algebra, we can rearrange this equation: array length = array size / element size. sizeof(array) is the array size, and sizeof(array[0]) is the element size, so our equation becomes array length = sizeof(array) / sizeof(array[0]). We typically use array element 0 for the array element, since it’s the only element guaranteed to exist no matter what the array length is.

Note that this will only work if the array is a fixed-length array, and you’re doing this trick in the same function that array is declared in (we’ll talk more about why this restriction exists in a future lesson in this chapter).

When sizeof is used on an array that has been passed to a function, it doesn’t error out like std::size() does. Instead, it returns the size of a pointer.

Again assuming 8 byte pointers and 4 byte integers, this prints


Author's note

A properly configured compiler should print a warning if you try to use sizeof() on an array that was passed to a function.

The calculation in main() was correct, but the sizeof() in printSize() returned 8 (This size of a pointer), and 8 divided by 4 is 2.

For this reason, be careful about using sizeof() on arrays!

Note: In common usage, the terms “array size” and “array length” are both most often used to refer to the array’s length (the size of the array isn’t useful in most cases, outside of the trick we’ve shown you above).

Indexing an array out of range

Remember that an array of length N has array elements 0 through N-1. So what happens if you try to access an array with a subscript outside of that range?

Consider the following program:

In this program, our array is of length 5, but we’re trying to write a prime number into the 6th element (index 5).

C++ does not do any checking to make sure that your indices are valid for the length of your array. So in the above example, the value of 13 will be inserted into memory where the 6th element would have been had it existed. When this happens, you will get undefined behavior -- For example, this could overwrite the value of another variable, or cause your program to crash.

Although it happens less often, C++ will also let you use a negative index, with similarly undesirable results.


When using arrays, ensure that your indices are valid for the range of your array!


1) Declare an array to hold the high temperature (to the nearest tenth of a degree) for each day of a year (assume 365 days in a year). Initialize the array with a value of 0.0 for each day.

2) Set up an enum with the names of the following animals: chicken, dog, cat, elephant, duck, and snake. Put the enum in a namespace. Define an array with an element for each of these animals, and use an initializer list to initialize each element to hold the number of legs that animal has.

Write a main function that prints the number of legs an elephant has, using the enumerator.

Quiz answers

1) Show Solution

2) Show Solution

10.3 -- Arrays and loops
10.1 -- Arrays (Part I)

366 comments to 10.2 — Arrays (Part II)

  • Waldo Lemmer

    Question #1:

    - > Declare an array to hold the high temperature (to the nearest tenth of a degree) for each day of a year (assume 365 days in a year).

      What's the "to the nearest tenth of a degree" part for?

    - Solution:


      Since you're explicitly telling us to initialize it to 0.0, I think it should be "{ 0.0 }".

  • UnknownLearner

    I've some warning here

    in order to I have to prefer enum class over enum. How I understand in this case it good using enum? Thanks guys for your website

    • I am no expert but I read some documentation about enums . Normal enum members are in the same scope as the enum while enum class members are in the scope of the enum

      e.g :

  • Rodrigo Silva

    Hello, thanks for the awesome work

    I am working on VS2019 windows7, x86 the code below. I want use N=5e5, but for some reason VS failed and says:
    exited with code -1073741571

    I think there is some memory problem because when I use N=2e5 there is no problem, but the same isse appears when N=3e5
    Thanks in advance


    #include <iostream>
    //#include <bitset>
    using namespace std;

    int main()
        const int N = 5e5;
        float x[N]{};
        cout << N;

    • Rodrigo Silva

      I found the answer to this question in chapter 9.14: Dynamically allocating arrays
      The problem, I think, it is that c++ uses a "small" memory to allocate variables, if a "bigger" one is needed to allocate an array of, for example, 5e5 elements, then it has to be used new[] and delete[] commands. The code below works. Thanks!

      #include <iostream>
      //#include <bitset>
      //#include <string>
      //#include <string_view>

      using namespace std;

      int main()
          int N = 5e5;
          float* array{new float[N]{}};
          cout << array[N-1] << endl;
          delete[] array;
          return 0;

  • Mateusz Kacperski

    Thank you guys for this webside ! I spend all my free time for learn cpp here :) i hope one day i can change my job for cpp programmer :) God bleess you <3

  • Apurva

    I am not able to understand below line from tutorial -

    "Note that due to the way C++ passes arrays to functions,
    std::size() function will not work for arrays that have been passed to functions!"

    Will you please explain why size() doesn't work for function parameter array? Arrays are passed as reference to function, so its the actual array, then why its size cannot be calculated in function? Please help.

    • Alex

      With built-in arrays, arrays decay to a pointer when passed to a function, and std::size can't determine the size of the array from a pointer.

      If you pass an array by reference (or use std::array instead) then std::size will work as expected.

    • Apurva

      Thanks for explanation. Its clear now.

  • Earl

    I wanted to incorporate some of the earlier lessons, so I went ahead and came up with this.

  • nuth vireak

    Hello in Quiz 2 should I use Enum or Enum Class? and which one is better?

    This is my code for Quiz 2 using Enum Class

    • nascardriver

      In this quiz, `enum` is the better choice, because you want to use the enumerators as indexes. With an `enum class`, you need to cast the enumerators every time you want to use them. The `namespace` around the `enum` protects the enumerators from colliding with other `enum`s. That's no necessary for `enum class`, because it is scoped.

  • nuth vireak

    Hello I have this problem

    The output look fine as you said :

    Original Value: 1                                                                                                                                                                  
    After Pass Value: 1                                                                                                                                                                
    Original Array: 1 2 3 4 5                                                                                                                                                          
    After Pass Array: 2 4 6 8 10

    But when I try this type of array

    Original Value: 1
    After Pass Value: 1
    Original Array: 1 2 3 4 5
    After Pass Array: 1 2 3 4 5

    "After Pass Array" still the same as "Original Array"

    • nascardriver

      `std::array` is copied by default when you pass it as an argument. If you want to modify a `std::array` that you've gotten as an argument, the parameter needs to be a reference (Chapter 10).

  • kwy

    for some reason my compiler doesn't recognise list initialisation, an error always pops up. i am using the Mac terminal and i just checked that i have the Apple clang version 11.0.3 and im not sure if i should update it?
    i also don't know how to update it but it's just really weird that list initialisation doesn't work?

  • TimT

    I'm running into an issue with std::size(array_name) in C++17: it's returning the size_t data type, so the compiler gives a "possible loss of data" warning unless I static-cast it to int.

  • J34NP3T3R

    As a side note, if you want to ensure a function does not modify the array elements passed into it, you can make the array const:

    // even though prime is the actual array, within this function it should be treated as a constant
    void passArray(const int prime[5])
        // so each of these lines will cause a compile error!
        prime[0] = 11;
        prime[1] = 7;
        prime[2] = 5;
        prime[3] = 3;
        prime[4] = 2;

    if you make the array parameter constant, does this mean it will only accept constant arrays passed to it ?
    will it generate an error if you make the parameter constant but the caller sends a non-constant array ?

  • Patrick

    Small change - In the first sentence, it should be "lesson 9.1" instead of 6.1

  • J34NP3T3R

    1.) because arrays themselves are passed to a function Does this mean ARRAYS are somewhat GLOBAL scoped or have linkage of "EXTERNAL" ?

    2.) it was suggested above to use sizeof instead of std::size() but i thought both returns different results ?
    being that std::size() returns the number of elements in the array
    and sizeof returns the size of the data of the array 2bytes 4 bytes etc.

    3.) in the two examples
        std::cout << "The array has: " << std::size(array) << " elements\n";

        std::cout << std::size(array) << '\n'; // will print the size of the array

    they look the same to me. using std::size(array).. how come one is expecting the number of elements in an array and the other the size of the array ? one is like array[5] = 5 elements and the other is integer size of an array * number of elements etc.

    • nascardriver

      1.) No

      2.) Where's that recommendation? Use `std::size`. If you can't use `std::size` because you can't upgrade your compiler, you have to perform the calculation shown in the lesson.

      3.) They're the same. Both are expecting an array and return the number of elements in that array.

  • I love you guys! This was my initial stab at the quiz without looking at the solution!

  • Jacob

    I'm having a problem understanding the motivation in the section "Arrays and enum classes".

    Why should I declare an enum *class* for students?  It just generates the error you warned of and then your solution was top declare the enum in its own namespace.  However, what I did here works just fine: No class needed, no separate namespace needed.

    More diplomatically: What advantage is there to be gained by using the "enum class" with the then-necessary separate namespace?  Better question: What can I do with the enum class & namespace method that I cannot do with the simpler code below?

    Thank you so MUCH for this!

    • nascardriver

      Enumerators of an enum are visible in the namespace the enum is declared in. If you don't encapsulate the enum in a user-defined namespace, the enumerators take up names in the global namespace.
      `enum class` also works, because its enumerators aren't accessible without the enum name.

  • yeokaiwei

    Instead of

    I got

    What is going on?

    I did get the C6384 warning.
    C6384 Dividing sizeof a point by another value.

    2. Why is the temperature example here? It isn't used at all.

    • nascardriver

      1. A pointer on your system has the same width as an `int`.

      2. The temperature example is used to show initialization to 0, because a lot of readers got it wrong.

      • yeokaiwei

        1. If I understand it correctly, I have a 8-byte pointer like you. Then, for some reason, my integers are set at 8-byte. Thus, 8/8 = 1. May I ask where are the default sizes of integers set? Why are my integers different from yours?

        2. Got this part. I naturally assumed default 0.

        • nascardriver

          I suppose you have 4 byte pointers, I don't think I've ever seen 8 byte `int`s.
          There are no default sizes.
          Are you maybe compiling in 32 bit mode? That would cause you to have 4 byte pointers.

          • yeokaiwei

            Yes, I am compiling in x86 or 32 bit mode.

            The issue is solved, it is as you said, I got 8 2 when I compiled in x64 mode.

            Perhaps, it is important to tell students which mode to compile in?

            It is not mentioned in the tutorial and such large variations in answers will definitely confuse students.

  • Marcus Holloway

    "whatever value 0 converts to for a non-integral fundamental type -- e.g. 0.0 for double). This is called zero initialization"

    I thought double is an integral, a fundamental integral.

  • Rolf004

    #include <iostream>

    namespace Animals
        enum Animals
        chicken,     //0
        dog,         //1
        snake,       //5
        allAnimals  //6

    int main()

    int beasts[Animals::allAnimals]{ 2, 4, 4, 4, 2, 0, }; //initializer list holds the number of legs for each animal

        std::cout << "The number of legs that an elephant has is: " << beasts[Animals::elephant] << '\n';

        return 0;

  • 1: double temperature[365] { };

    2:#include <iostream>

    namespace Animals
        enum Animals // The name of this enum could be omitted since it isn't used anywhere

    int main()
        int legs[Animals::max_animals]{ 2, 4, 4, 4, 2, 0 };

        std::cout << "An elephant has " << legs[Animals::elephant] << " legs.\n";

        return 0;

  • Tony

    My solution to quiz 2 :p

  • sims7564

    On a machine with 4 byte integers and 8 byte pointers, this printed:


    Assuming 4 byte integers, this should print:


  • Jimmy

    I read somewhere that if i use static_cast on enum class then maybe I shouldn't use enum classes in the first place. Is this true? if it is what are some alternative solution to this ?

    • nascardriver

      You don't need to wrap `Animal_Type` in a `namespace`. `enum class` only allows scoped access, making the namespace redundant.
      If you're using an `enum class` to index an array, you'll have to use a `static_cast` every time you use an enumerator. In that case, a regular `enum` inside a `namespace` can be a better choice, because it is implicitly convertible to `int`.

  • ammawn

    "sizeof isn’t as easy to use and std::size()"
    should be
    "sizeof isn’t as easy to use as std::size()"
    i think

  • Arvand


    the output of my code:
    max_animals: -858993460
    A duck has 2 legs

    can someone please explain to me why the max_animals holds that arbitrary (or not arbitrary) value?

  • samira

    Does my solution look good for question #2?

    • nascardriver

      In your switch-statement, you're switching an enum, so your cases should check for enumerators, not integers. If you use integers and you modify the enum, your code breaks (Because the integers are no longer correct).
      Note that `Animals::NUMBER_of_ANIMALS` in line 49 has no effect. You can keep it for documentation purposes, but practically it's the same as

      • samira

        Thank you so much for your tips.

        I modified it.

        Q1: I got the warning "enum type Animal::Animal is unscoped, prefer 'enum class' over 'enum'. Although we use namespace for 'enum', I was wondering why we still get this warning?!

        Q2: what is the wrong with having switch cases integers instead of enumerators as behind the scenes they are converted to their integer equivalents ?

        • nascardriver

          Q1: Even when nested in a namespace, an `enum` can still be misused, eg. by using integers in a switch. An `enum class` wouldn't have allowed you to do this.

          Q2: Magic numbers are bad. No one except you in this moment knows what they mean.
          If you update `Animals`, you code breaks. For example, if you remove `CAT`, `getAnimalName` returns wrong results. If you add an animal and don't add it to the end of the enum, your code breaks. Just because 2 things have the same value doesn't mean you can interchange them.

  • ZAbih

    > Note that this “trick” only works if you do not change the enumerator values manually!
    Is that OK if we change the order of enumerators and add enumerators from the top, like the following ? Then what happened to this code below?

    • nascardriver

      The code continues to work as expected, as long as you're using the enum consistently. If you're using a manual index somewhere, you'll break your code.

  • Eric

    Quiz 1:
    Did I misinterpret? I thought it was suggested to use:

    "As of C++11, the uniform initialization syntax should be used instead:

    but the quiz answer is

    I wrote a function to loop through and initialise all elements to 0.0.

    Thanks for a confirmation!

    • nascardriver

      The quiz is using list (uniform) initialization, it's just that the list is empty. This causes all elements to be initialized to 0.

  • Taras

    Hi dear teachers! I tried to solve task 1 but has faced the wrong output. I expect to see 0.0 but it outputs only 0.  Can't figure out what I have missed.

    • nascardriver

      You need to add `std::fixed`

      That way the decimal places are printed even if they're trailing zeroes.

  • Gabe

    Quiz 1

    Quiz 2

Leave a Comment

Put all code inside code tags: [code]your code here[/code]