9.2 — Arrays (Part II)

This lesson continues the discussion of arrays that began in lesson 9.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

9.3 -- Arrays and loops
9.1 -- Arrays (Part I)

349 comments to 9.2 — Arrays (Part II)

  • Dudz

    My answer for question#2

  • Petar Jukić

    Hello, I'm just revisiting this chapter, I'm currently reading 6.8

    So what is actually difference if we

    declare as

    so, what we can and what we can't do if we remove that number 5 from function


    • nascardriver

      The 5 doesn't do anything.

      all the same.

  • Ayrton Fithiadi Sedjati

    In the fourth code (snippet) in this lesson, I believe you have mistakenly typed "double darray[5]" instead of "double array[5]".

  • Nathan

    So, I was wondering if there was a quick way to do this?

    • nascardriver

      You can use `std::array` instead of a regular array.

      `std::array` is covered later, you should be able to understand it if you know regular arrays.

  • m3loo


    I wanted to make a tic tac toe game and used a 2d matrix. while programming I noticed something I coudnt undertstand, here is the code:

    so if I run the programm I get the numbers from 49-57 and if I change "int matrix[3][3]" to "char matrix[3][3]" I get the numbers from 1-9. why is that?

    • Alex

      You're initializing your int matrix with char values -- these get stored as their ASCII value equivalents ('1' is stored as 49, not 1). Thus, when you print them as integers, you get 49, not '1'. If you switch matrix to char, these print as chars instead of integers (where value 49 prints as character '1').

      Since matrix is an int matrix, you should be initializing it with integer values, not char values.

  • Elvis

    Love the south park reference

  • Conner

    Hi! In the text below the example given under "Indexing an array out of range", it says that we're trying to write a test score, but we're trying to write a prime number.

  • Zwaffel

    Hey, i solved the second question at the end of this chapter a bit diffrently.
    I used a enum class to force the Animal prefix instead of using animal namespace with a normal enum

    versus that the solution had.

    Which would be preferred? In my eyes these are 2 ways to get to the same result.

  • Daniel

    Hey would you ever actually use this kind of code? Or is it just and idea until we get to know for example std::map?

    • nascardriver


      if you need the performance, yes. `std::map` has overhead, because it has to to find the entry. By using an array with fixed indexes, we can calculate where the entry is.
      You wouldn't do this with student names, as they are unknown at compile-time.

  • hellmet

    Whoa whoa there! So you're telling me, std::size can take a array as argument and return a valid size but a function that uses the same argument and uses sizeof doesn't work! That's some sweet mechanics happening in std::size then! Would be nice to point that out! Adddnn, I can't use std:size in a function! So much happening!

    • Yep, `std::size` can't extract any more information from a decayed array than `sizeof` can. C-style arrays should be avoided anyway, use `std::array` and `std::span` (`gsl::span` if pre C++20) instead, they store the size.

    • Constantine

      I've just looked. It turned out that std::size is a very short template function. You can write it yourself if don't use c++20 yet. I simplified it a little for readability and added another similar function:

  • Parsa

    std::size results in an error for saying std namespace has no member ssize

    • Enable a higher standard in your compiler's settings.
      `std::size` needs at least C++17
      `std::ssize` needs at least C++20 (Probably not supported yet)

    • hellmet

      You can try and fix that by changing some of your compiler flags. For Visual Studio and Code blocks, you can add the flag '/std:c++17' and check if that works.

      For gcc, add '-std=c++17'. So the whole command would like so.

  • Benur21

    How about passing an array as argument to a function, but the function has an array with a different lenght in its parameter?

  • Lawrence

    Why are the namespace and enum names the same? I'm guessing Animals in the main() is referring to the namespace?

    • I don't know why Alex choose to do this. You're right, `Animals` in `main` is the namespace. The enum's name is never used and can be omitted.

      • Alex

        I gave the enum a name here because I hadn't previously covered the fact that enums can be anonymous.

        I've updated the article on enums to note this, and added a comment around the fact that the enum could be made anonymous.

        • daniel

          where did u cover anon enums?

          • Alex

            I mentioned it in the lesson on enumerated types when I said, "Providing a name for an enumeration is optional, but common". I added a note to that lesson to note that these enums are sometimes called "anonymous enums" just in case anybody is searching for that term.

            • Rob

              Still a bit confused about named/anonymous enums. Given that the solution does name the enum, I was expecting to see namespace_name::enum_name::ENUMERATOR, i.e. Animals::Animals::ELEPHANT and that's how I did it in my solution. Clearly it still works if we just do namespace_name::ENUMERATOR, so does that mean that all enums within a namespace can be treated as if they were anonymous, even when we do actually give them a name?

  • Lorenz

    Little thing: you are missing

    in the second solution.

    And a question for you: in the previous chapters you always recommend to use uniform initialization for variables, what about arrays? is it also better or can I use =?

    Thank you

  • Red Lightning

    If const is a run-time constant (And constexpr is compile-time), how does this example work? these are fixed size arrays.

  • Alireza

    Hello there,

    I just tried this piece of code and it gave me an undefined behavior.

    As I have understood, the @aa array can access the other bits which are not in the range of the array.
    So it can change the other bits and can make some bugs not to have security.
    What should we do in these cases ?

  • Dimbo1911

    Good morning, I have a simple question, is there any convention how to break up the initialization of a table (when it gets over 80 columns, for redability on smaller monitors)? I did it like this but do not know if it is correct.

  • MasterOfNothing

  • YTXbaiaLrs

    In the code example for "Determining the length of a fixed array as of C++17",

    is missing. Also, I do not get the same output as you: "The array has 8elements" (missing space after 8).

  • Nathan

    I’m creating a game and have X and Y coords.  Currently, I’m trying to implement walls, should I use an array to hold all of the walls X and Y coordinates (to check agensed current position)?  A struct? Have any suggestions?

    • 1 wall segment is an instance of a struct (Containing wall material, type, etc.).
      Multiple walls are stored in an array.

      • Nathan

        Thanks, that would be pretty interesting

      • Nathan

        Do you have any suggestions on how I would format that?

        • I have little information about your game.

          • Nathan

            So far, the entire game is math based, and in the console.  I did figure it out though.  Thanks!

          • Nathan

            If you had a more efficient way to do this, it would be appreciated


  • Okorie Emmanuella

    I tried writing a code where i declared my array as a char type. After which i tried to compare some elements of the array with
    with boolean expression ==  to my surprise, it gave me an error;
    error: ISO C++ forbids comparison between pointer and integer [-fpermissive]

    Please what really is the problem and how can i solve it?
    Here is my code

    Also, i would really appreciate any other corrections or additions you might have.

    Thank you :)

    • * Line 8, 11, 14, 23, 24, 25: Limit your lines to 80 characters in length for better readability on small displays.
      * Use '\n' instead of @std::endl
      * Use the auto-formatting feature of your editor
      * @i never changes
      * Avoid global variables
      * Re-read the lesson on loops
      * Use a bool for binary variables

      Your code looks like you skipped several lessons and/or didn't do the quizzes. You'll run into a lot more problems.

  • hassan magaji

    Hi Alex,
    what about designated initializers and compound literals?

    • Alex

      Designated initializers are proposed for C++20, which hasn't been finalized yet. Compound literals are a C99 concept, not C++, and better options exist in C++ to do the same thing (create an anonymous std::array).

  • Hi Alex!

    The sizeofs should be replaced with @std::size. It's more versatile, up-to-date and easier to understand. This affects all subsequent lessons.

  • Jon

    Hi! Quick question about the last example in the "Arrays and enum classes" section. Do you recommend using a standard enum inside of a namespace, or just using a standard enum without the namespace like you did in the "Arrays and enums" section above that, and why?

    Thank you!

    • > using a standard enum without the namespace
      Don't use a standard enum unless it's encapsulated (eg. in a namespace or class).
      Use one of the ways shown in the "Arrays and enum classes" paragraph.

  • Rai

    I can't get this to work!!

    The error messages are:
    error C2664: 'std::string getAnimalString(int [])': cannot convert argument 1 from 'int' to 'int []'
    note: Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast

    These are for  getAnimalString(animal[die(mersenne)])

    • Rai

      I just fixed it with this.

      One problem is that The number generated of die(Mersenne) for getAnimalString is different to the one for legs[]. This gives something weird like "A cat has 2 legs" or even "a snake has 4 legs." If lucky it will give "A cat has 4 legs." How do I make it so the number generated for both die(Mersenne) is the same.

      Also how could I improve this code.

      • Rai

        Fixed with this

        int generated = die(mersenne)

        std::cout << "A " << getAnimalString(animal[generated)]) << " has " << legs[generated] << " legs.";

        • Benjamin

          You missed the point of using the enum as the index of the legs array.

          Check out lines 54 & 55 of my code.

  • Stefen Zaki

    can you initialize an array to zero by doing the following ?
    int array [arraySize] = {0};

    • That zero-initializes the entire array.
      Your version also does it, but the 0 in the curly brackets only sets the first element to 0, which is 0 anyway.
      If you want to initialize to a non-zero value, you can use @std::fill

  • Shawn

    On quiz 2:

      int legs[Animals::MAX_ANIMALS] = { 2, 4, 4, 4, 2, 0 };

    why can't we just do:

    int legs[] {2, 4, 4, 4, 2, 0};

    • You can do so. The benefit of explicitly specifying the size is that if you changed @MAX_ANIMALS but forgot to update @legs, you'd get a compile-time error or warning.
      Uniform initialization should be used either way.

  • C++guy

    There's something I didn't understand with what is said about the argument being copied when there's a function call.
    When you make a function call, the parameter of the function is created and initialized with this argument right ? (if not, how does it works ?) So even if I assign a new value to the parameter like you did in the example it doesn't affect the argument.
    It's like saying int value = y then writing value = 2, only the value of value changes but not y right ?

    • > the parameter of the function is created and initialized with this argument

      > It's like saying int value = y then writing value = 2, only the value of value changes but not y
      right. Lesson 7.2, 7.3 and 7.4 cover this in more detail. I like your example.

  • Eric

    Maybe I'm missing something but in the passing arrays to functions, why did "before passArray" print out backwards?

Leave a Comment

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