Search

6.2 — Arrays (Part II)

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

Fortunately, C++ provides a more convenient way to initialize entire arrays via use of an initializer list. The following example is equivalent to 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. The following example shows this in action:

This prints:

7
4
5
0
0

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

In C++11, the uniform initialization syntax can be used instead:

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:

sizeof and arrays

The sizeof operator can be used on arrays, and it will return the total size of the array (array length multiplied by element size). Note that due to the way C++ passes arrays to functions, this will _not_ work properly for arrays that have been passed to functions!

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

32
4

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

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

Determining the length of a fixed array

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 prints:

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).

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). In these tutorials, we’ll try to use the term “length” when we’re talking about the number of elements in the array, and “size” when we’re referring to how large something is in bytes.

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 test score 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.

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

Quiz

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

6.3 -- Arrays and loops
Index
6.1 -- Arrays (Part I)

130 comments to 6.2 — Arrays (Part II)

  • J3ANP3T3R

    Quiz answer 1 :

    double temperature[365] = { 0.0 };

    isn’t this going to initialize the first element only ?

  • J3ANP3T3R

    how does using a standard enum inside a namespace work again ? how does it fix the problem with enum not having an implicit conversion to integer?

    • Alex

      A standard enum inside a namespace works just like a standard enum outside of a namespace, you just need to prefix it with the namespace name to use it.

      Enums DO have an implicit conversion to integer, but enum classes do not. When using enumerators as array indicates, enum is easier than enum class because of this implicit conversion to integer. With enum class you have to use lots of casts to do conversions, which is a pain.

      However, enumerated types are often declared globally (since they’re needed in many places), and they tend to pollute your global space with the enumerator names. For this reason, putting the enum in a namespace helps keep things clean and prevent naming collisions.

  • derpasaurus

    Is there any way to assign a value to an array value using uniform initialization? Something like this? (I’ve tried it, does not compile)

  • Jim

    Alex,
    Small error, there are 2 that’s in the first sentence below.

    Arrays and enums

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

  • Ahmed Gamal

    I tried to set a size for a fixed array to a number entered by the user and it works !!
    i am using codeblocks

    • Alex

      This is called a variable length array. Your compiler may support them for C99 compatibility purposes, but it is not currently part of the C++ standard.

  • Bede

    Hi Alex, just some minor improvements for this chapter:

    In the solution of Quiz 1, define the array with 366 elements (not 365), just in case it’s a leap year.

    sizeof(any_pointer) could also be 8

    By the way: Thanks for this great tutorial.

  • Benjamin

    You can pass an array to function without the ‘corruption’ of an array by reference.
    Syntax:

    However whenever it is done, The size of the array passed has to be specified.

    sample code :

    output:
    Index :  39
    sizeof() used : 20
    Index :  59
    sizeof() used : 20
    Size of int : 4
    Size of that array : 20

    [runned on http://cpp.sh]

    P.S. Due to this complex syntax and necessity of using templates
    for flexibility, I’m considering about using std::array instead.

    • Benjamin

      The reason why I am referring this is to figure out why an array passed by reference doesn’t corrupt (does not be converted implicitly into pointer, and does remember the size). If someone tells me the reason why, I’ll be appreciating whoever answers.

      • Alex

        Passing an array by reference passes the actual array argument, not a decayed pointer to the array. This allows you to retain the type information, from which (in the case of fixed arrays) the size can be derived.

    • Darren

      As a side note if you divide the sizeof(array) by the sizeof(array[0]) you get the length of that array. In output above that is 20 (bytes) / 4 (bytes) equal to a length of 5.

      • Alex

        This is a cool trick that I used to recommend, but it only works if array hasn’t decayed into a pointer. Never-the-less, I’ve added a note about it back into the tutorial, along with the appropriate caveats.

  • Lokesh

    Hi Alex,
    In the "passing arrays to functions section", why is the compiler not causing a "conflicting declaration" error after re-declaring the array as <const int> from <int> since it is the same array? Can we change the type of a variable(I guess a pointer here) when passed to a function like that?

    • Lokesh

      @Alex,
      I think I got it. I think, a pointer of type <const int> is declared and the contents of the pointer to the array(which is of type <int>) is copied to it.

    • Alex

      Yes, it’s fine to declare a function parameter as const and then pass a non-const argument into it. The parameter will be treated as const in the scope of the function.

      C++ will willingly convert non-const types into const types (just not the other way around).

      • Lokesh

        Oh, I see, const is a modifier. Thanks 🙂

        • Alex

          I may have given you the wrong impression, so I’ve updated my answer. Although the const keyword is a type modifier, it’s also considered part of the type. However, this isn’t a problem since C++ will willingly do the conversion from a non-const to a const type.

          • Raquib

            Hi Alex & Lokesh,

            When I was going through this I also had the same question, and I wrote it down in my notebook to ask later once I finish the chapter, in case I figure it out myself, Alex explains later on or answers in the comments section. So my original question was similar to Lokeshs-

            Q> Will this change the type of original array to "const int" permanently from originally declared as "int"?? or is this going to happen only inside the scope of the function and the original array will still be an "int".

            Then I tried this to see what’s happening-

            Prints-
            1 2
            12 13

            So definitely I did not get any errors. Meaning only inside the function scope the array is ‘treated’ as if constant (not modifiable) it doesn’t effect or change the type the original array is. This makes me wonder what ‘const’ actually does in the system.

            One thing that I can think of goes like this. When we pass a int variable
            say,

            to the function as argument say,

            and declare & define the function with parameter of same type say,

            instead of something like,

            The function has both Read/Write privilege to that memory location. But, when you specify ‘const’ in the func parameter it just means the function only has Read privilege and no Write privilege to that particular memory location allocated. specifying Const maybe just does that in this context.

            I am not sure. But, that’s what I think is happening. Alex can shed some light on this if I am correct.

            Thanks. 🙂

            • Alex

              You are correct. When we pass a non-const argument to a const parameter, the parameter treats the argument as const, but the argument retains its original type.

  • Aymen

    Hey Alex, had a go at creating my own little program.

    Is there a way to avoid using the ZERO in the enum pokemon and could the program I have written below be written without the need of the enum pokemon. If so , then what is the point of having it in the first place.

    Cheers again!

    • Alex

      Try this:

  • Jim

    Alex,

    In this cast you wrote above:

    "int testScores[static_cast<int>(StudentNames::MAX_STUDENTS)]; // allocate 6 integers"

    Why did you place the array operators where they are shown? This was not covered in lesson 4.4.

    • Alex

      I’m not sure what you mean. This is the equivalent of:

      What are you confused about?

  • Rob G.

    "However, if there are less initializers in the list than the array can hold, the remaining elements are initialized to 0."

    Answering my own question, sorry for prior post!

    output: index 1:23.6 followed by 364 zeros.

  • Rob G.

    Question 1 was a sheer surprise to me-elegant as usual Alex!

    can’t get code tags to work

    Mine is 3x longer. What is the take home lesson on this? How does one initialized value list in your solution zero the array?

  • Roee Sefi

    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,

    Did u mean "if" existed?

  • UnixIsVerySimple!

    Thank you Alex for such a nice tutorial

  • GS

    please for everything u teach please give a complete example coding and harder complete coding so that we can know ……tq

  • Two questions:
    If arrays can hold more than one integer (or doubles), why I get 4 as output when using sizeof to know the size of an int array of length 30. If it can store 30 different variables, size should be 120 bytes or ++

    If the actual array is passed to a parameter, why we are allowed to use different names of an array in declaration and different as parameter

    And typos:

    Remove still works from comment, because you are using an enum class and it wont work anymore
    Thanks 🙂

    • Alex

      You can use sizeof on arrays, and it will tell you the size of the array in total (array length * element size). However, if you pass an array to a function, this will no longer work, because the array “decays” into a pointer, so you end up getting the size of the pointer instead. C++ is weird that way.

      > If the actual array is passed to a parameter, why we are allowed to use different names of an array in declaration and different as parameter

      Names are just names. If you want to call the array something different in the function, you can. This allows us to be able to write the function without having to know what the name of the argument being passed in is. Otherwise our functions wouldn’t be very reusable.

  • Shivam Tripathi

    okk…:-)

  • Shivam Tripathi

    Alex…instead of declaring array with an "int" type…can’t we declare this array with "Animals" enum type????

    • Alex

      It wouldn’t make sense to do that. Each element of the array needs to hold an integer (to represent the number of legs the animal has).

      The enum should be used as the index to select the type of animal to get the number of legs for.

  • cpplx

    can you provide enum class (C++11) variant of solution to quiz2?

    • C++ newbie

      • cpplx

        does not compile. if it was that easy i wouldnt be posting for it

      • Alex

  • Deses

    First of all, thanks a lot for the tutorial thus far.

    Second, I used the enum class instead of enum as recommended elsewhere in this tutorial. This resulted in compiler error since enum class apparently has a non-integer type definition. I got around the issue by using static_cast to convert MAX_WHATEVER to integer. Is this the solution you would recommend or is there a better way around?

  • James

    The last enumerator equaling the size of the array is very clever.

  • Jim

    This is a great site. Very well written. I ve learned so much very quickly.
    A question: When I use the

    inside of a function it does not work. It gives always "1". Why is that? Following is the code I ve written. Any help would be appreciated.

    • alan

      Jim,
      the line in the function does work and correctly gives a result of 1, which is the size of the ‘arr’ array.
      int arr_len = sizeof(arr) / sizeof(arr[0]);

      The problem is you can’t pass an array to a function, only a pointer to the array.
      You then need to determine the length of the array in main() and pass it to the function as a separate parameter. (described by Alex in a later tutorial).
      Not sure what the functions ‘distance’ and ‘find’ are doing but I expect you always get 20.93 because loc = 1 thus always points to the 2nd element.

      Probably frowned on but I’ve rarely used arrays (other than strings), when I have I tend to declare them globally (like you did), then their content, length, etc can be referenced anywhere in the code.
      For Example you could have used;
      int arr_len = sizeof(DN) / sizeof(DN[0]);
      in the function, and not needed to pass the array.

      Alan

  • replax

    This is the print app for exercise 2:

    thanks for the free tutorials btw, theyre great!!

  • Hello Alex,

    Can you help me in understanding the following program?
    The motive of the program is to ask the user as many numbers as he wishes, and then if he want to stop he can enter zero(0) value. Once that is done, the program will show how many elements he had entered to the array.
    But the following program prints out incorrect values and crashes. I can’t figure out what is going wrong and where.

    The Code:

    The Output:

    Regards,
    Mayur

    • caboosethepantless

      The compiler needs to know how big the array is at compile time, which means…

      … is telling the compiler that when the program is run, to allocate space for one element, and store 0 in element 0.

      Since your array only has one element, trying to store values in the non-existent element 1, element 2, or so on will cause the program to be unstable.

      • Mayur

        Ahh!! of course. So isn’t there anyway we can declare an array of indefinite size and according to the input, let it calculate itself what the size should be ?

        • Tom

          Ahh!! of course. So isn’t there anyway we can declare an array of indefinite size and according to the input, let it calculate itself what the size should be ?

          Yes, there is a way to do that, but that is a more advanced topic that is covered later, in section 6.9 (Dynamic Memory Allocation).

  • Shawn

    Lol south-park 😛

    anyways so far, i am loving your tutorials
    thanks you guys for the tutorials

  • Joshua Sinkfield

    Why wouldn’t this work

    I fixed the problem but just want to know what happens. Is it because the array becomes as member?

    • twilight

      I think it is because you declared an array of structs, namely as many as your NUM_ANIMALS - thing is.

      And then you are trying to assign multiple values to one integer in ONE of your structs.

      Think about it, say NUM_ANIMALS was 5.
      Then there are 5 arrays, 0 - 4. And now you try to access anAnimal[5] because NUM_ANIMALS is still 5, but there is no array 5, it is just 0 - 4.

      Aditionally nLegs is probably just an integer and declared as such. You are trying to make an array out of an Integer that is no array; inside a struct that does not exist.

  • Chris

    In the solution to the first quiz, why did you use a double? To waste space? A float uses less space on some peoples’ PCs and you specifically mention temperatures that only go to the tenths place. Unless we’re going to be having some serious scorchers (over 15 digits long), I highly doubt the double is necessary.

    • Well, actually you can hardly see a float type in C++ now. Creator of C++, Bjarne Stroustrup doesn’t even mention about floats in his beginner book.

      • Xanth

        Haha that doesn't answer any of the points in the question. And I had a similar question. If you're trying to make your program as efficient as possible, you could use a float here to save yourself 4 bytes of memory.

  • Zak

    And thanks so much. This tutorial is so well done.

  • Chiamaka

    for question #2 would the answer still have been right if instead of using “MAX_ANIMALS” for the array you just used the number “6”?

  • Frank

    Can you initialize an array and omit the size inside a class?
    (See OMITTED SIZE above)
    I think the answer is no but I don’t understand why?

    This is fine.

    This is NOT.

    Why is that not allowed?

    • Because you are not allowed to initialize variables in a class declaration. You have to initialize them in a constructor, which means this kind of syntax isn’t possible.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter