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!

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:

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.

But 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, and likely causing your program to malfunction. 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)

101 comments to 6.2 — Arrays (Part II)

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

  • 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”?

  • Zak

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

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

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

  • Shawn

    Lol south-park 😛

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

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

  • replax

    This is the print app for exercise 2:

    thanks for the free tutorials btw, theyre great!!

  • 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

  • James

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

  • 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?

  • 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

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

  • Shivam Tripathi

    okk…:-)

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

  • GS

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

  • UnixIsVerySimple!

    Thank you Alex for such a nice tutorial

  • 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?

  • 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?

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

  • 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?

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

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

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

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

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

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

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

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

  • J3ANP3T3R

    Quiz answer 1 :

    double temperature[365] = { 0.0 };

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

  • Nyap

    y doesn’t this work

    /home/nyap/Projects/TicTacToe/main.cpp|43|error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]|

  • subh samal

    Hi Alex,

    I could not understand the reason behind the below differences when using enum inside namespace. Why typecasting is not required in the second case?

    case 1: Without namespace.

    enum class StudentNames
    {
        KENNY, // 0
        KYLE, // 1
        STAN, // 2
        BUTTERS, // 3
        CARTMAN, // 4
        WENDY, // 5
        MAX_STUDENTS // 6
    };

    int main()

    {
        
    int testScores[static_cast<int>(StudentNames::MAX_STUDENTS)]; // allocate 6 integers
        testScores[static_cast<int>(StudentNames::STAN)] = 76;
    }

    case 2: using namespace.

    namespace StudentNames
    {
        enum StudentNames
        {
            KENNY, // 0
            KYLE, // 1
            STAN, // 2
            BUTTERS, // 3
            CARTMAN, // 4
            WENDY, // 5
            MAX_STUDENTS // 6
        };
    }

    int main()

    {
        int testScores[StudentNames::MAX_STUDENTS]; // allocate 6 integers
        testScores[StudentNames::STAN] = 76;
    }

    • Alex

      Interesting question, but the wrong question to ask. 🙂 Remember that enums are placed into the same scope that they are declared in, so in the top case, KENNY, KYLE, STAN, etc… are all placed in the global namespace. It’s actually non-standard C++ to access an enum using the scope resolution operator -- Visual Studio lets you, as do some other compilers, but it’s non-standard behavior. So instead of StudentNames::STAN, you should just be using STAN in this case.

      In the second case, StudentNames:: is actually resolving to the namespace, with STAN resolving to the enumerator inside of the namespace. This is syntactically valid for all compilers.

  • KIRPAL SINGH

    array element 2

    Can you elaborate more on this statement? what did you mean when you said array element 2?

  • KIRPAL SINGH

    this is example from above:
    "StudentNames::STAN"

    what is the meaning of "::" after the enum StudentNames?

    • Alex

      :: is the scope resolution operator. What comes before the :: identifies the scope, and what comes after the :: identifies the identifier within that scope. So StudentNames::STAN means “Look inside the scope StudentNames for an identifier named STAN”. The scope could be the name of a namespace, enum, class, etc… If no scope is provided, then the global scope will be used (so ::Foo would refer to identifier Foo in the global namespace).

  • abolfazl

  • Jorge

    I am not using the "namespace Animals" and the code works fine, why?  Thanks, Jorge

    • Alex

      Enums put all of their enumerators in the global namespace (which causes a lot of namespace pollution). This means you don’t need to use the scope resolution operator (::) to access them. But it also means you will get naming conflicts if you have multiple enums trying to use the same enumerator (e.g. a Color enum and a Mood enum would have a conflict if enumerator Blue appeared in both).

  • Abdul Sami

    Dear Admin, i have a question about passing array as an argument to a function. when we call PassArray function by passing array then how it works ? Is the base  address passed or the whole Array etc??  

  • KIRPAL SINGH HARWAN SINGH

    int main()
    {
        int testScores[MAX_STUDENTS]; // allocate 5 integers
        testScores[STAN] = 76;

        return 0;
    }

    how will the compiler know where to find max_student since its inside enum studentname and not in main function… shouldnt it be like testScores[studentname.Maxstudent]… i am new to c++

    • Alex

      enums are a type, not an object, so you don’t need an object to access the enumerators.

      Also, enums put their enumerators into the surrounding scope (e.g. they pollute the scope they’re in). In the above case, the enumerators in StudentNames go into the global namespace, and thus are accessible from within function main().

  • KIRPAL SINGH HARWAN SINGH

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

    int main()
    {
        int testScores[static_cast<int>(StudentNames::MAX_STUDENTS)]; // allocate 6 integers
        testScores[static_cast<int>(StudentNames::STAN)] = 76;
    }

    can you explain a little further on this… i dont understand how this works… i am new to c++

    • Alex

      What part of this are you not understanding? enum classes won’t implicitly convert their enumerators to a integer, so we have to explicitly do so via static_cast.

  • KIRPAL SINGH HARWAN SINGH

    // 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 this will produce an error… what is the right way to make an array constant?

    • Alex

      I don’t understand the question. This produces an error because prime is constant, and the function is trying to change the value of the members.

      The problem isn’t prime, the problem is the code in the function body.

  • HWANG SEHYUN

    So, [int temperature[365]{}][/code] would initialize all the elements to 0.
    How about [double temperature[365]{}][/code]?? will this initialize all the elements to 0.0.

    In solution 1, I’m curious why you initialized 0.0 only to the first elements. Does [double temperature[365]{}][/code] works same for this?

  • HelloWorld

    Is it possible to get the array-length by dividing the sizeof(array) through sizeof(datatype of array)?

    E.g for int..

    int array[] { 1, 2, 3, 4};
    std::cout << "Array length: " << sizeof(array)/sizeof(int) << "n";
    //instead of sizeof(int) you use the sizeof(array[0])..if this is for making sure that the array is not un-initialized, then i get your point there.

    The math behind this is:
    sizeof(array) = 4*4bytes = 16 bytes
    sizeof(int) = 4 bytes
    sizeof(array[0]) = 4 bytes

    Right?

    So sizeof(array)/sizeof(array[0]) or sizeof(array)/sizeof(int) EQUALS (4 * 4 bytes) /4 bytes = 4 . The actual length of the array.
    Let skip the case where ints are 2 bytes..it would be the same math only 2 instead of 4 bytes. Still 4 entrys in the array itself. The last entry (4) is array[3] indexed to [3]. Indexing starts at 0 right.

    So the length of 4 would be great to work with in a for loop because we loop until array index [3] if we set the the loop like this :
    for (int i = 0; i < sizeof(array)/sizeof(int); ++i)
    {
    do somethings
    };

    Now….
    If I made an array like this:

    int array[4] {1, 2, 3, 4}; it would set the 5th array entry array[4] to 0 by default through initializing the array not just defining it

    So If I do the sizeof(array)/sizeof(array[0]) or sizeof(array)/sizeof(int) on this…

    Will this give me the same results as above, or will this happen:

    sizeof(array) = 5 * 4 bytes; //5 not 4 because the last array entry array[4] is initialized = 0.  That makes 5 initialized entrys

    1. array[0] = 1
    2. array[1] = 2
    3. array[2] = 3
    4. array[3] = 4
    5. array[4] = 0 // by default to 0, because the array is initialized(initializer list), not only defined/or declared(i dunno what term is actually right for this, I tend to defined?)

    sizeof(array[0]) = sizeof(int) = 4 bytes

    So this time sizeof(array)/sizeof(array[0]) or sizeof(array)/sizeof(int) EQUALS (5 * 4 bytes)/ 4 bytes = 5.

    It’s dangerous to use this length/s unknowingsly in for loops etc. For example calculations like a mean of a dataset need the exact amount of entrys. If the 0 and the length of 5 not 4 get calculated within the mean, the value is not representive for whatever, isn’t it?

    • Alex

      Yes, I cover both this trick and its limitations in the “sizeof and arrays” subsection as part of the lesson.

      If you do this:
      int array[4] { 1, 2, 3, 4 }

      there is no 5th element, so sizeof(array)/sizeof(array[0]) will give you the proper length of 4.

      It’s a neat trick, but there _are_ better options available (such as std::array) that I discuss later in the chapter.

  • Matt

    Alex,

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

    In context, I figured out what this sentence meant after reading ahead. But this sentence alone is a little ambiguous due to your use of the word "size" refering to two different things in the same sentence.

    • Alex

      Yeah, I agree, the overloading of the word size makes that hard to parse. I’ve updated the lesson to use the word “length” when I’m talking about how many elements are in the array, and “size” when I’m talking about how large something is in bytes.

  • Brankovich

    Why an out-of-range element can be accessed if I assign it to a value?

    • Alex

      C++ doesn’t do range checking for build-in arrays. Making sure your indices are all within range is your responsibility. If you fail to do so, the results are undefined. Your program may work fine, you may get a different result, or it may crash.

  • Alexander Kindel

    For the first quiz question, I assumed the idea was ensure that, whenever an element of the array is printed, it will be formatted with one digit to the right of the decimal place. In the given answer, I find that no matter how I enter a value, if there is a zero to the right of the decimal place not followed by a nonzero digit, that zero is omitted when the value is printed. For example, if I set an element to 2.0, it prints as 2. I recognize that this or any other single case could be fixed using setprecision(), but since that deals with total number of digits displayed, on both sides of the decimal point, while here the desired total number of digits varies depending on how many of them are to the left of the decimal place, I don’t see how it could be used in general. Is this something that hasn’t been covered by this point in the tutorial, or have I missed it?

    • Alex

      I’ve not covered how to print a fixed number of digits after the decimal point. Here’s how you can do that:

  • Paulo Mourão

    Hey Alex.
    Amazing tutorials, I’m learning a hell of a lot from this, thank you.
    I’m somewhat halfway through this one and I have a doubt. I tried searching on the comments section for this, but I didn’t find it (let’s hope I didn’t miss it, sorry if I did).

    It’s just that you said "Note that this “trick” only works if you do not change the enumerator values manually!". Why is that?

    • Alex

      Remember that each enumerator that isn’t given a value will take a value one greater than the previous enumerator. So if you don’t touch the enumerator values, then the MAX_ENUMERATOR will represent the number of other enumerators (itself excluded). This value can be useful in many different contexts, including setting the size of an array where you need one element for each enumerator.

      If you were to assign your own values to the enumerator, MAX_ENUMERATOR would likely end up with some other value that doesn’t represent the number of other enumerators in the array -- thus defeating the point of the trick.

      • Paulo Mourão

        AHH, that trick! I thought you were reffering to the whole thing of using enumerators in the first place. I thought the compiler would complain or something if you used enumerators whose values had been changed. My bad, misunderstood it there.
        Thank you for the quick response!

Leave a Comment

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