CS 70

Key Points

Arrays of Primitives

  • Arrays are
    • Fixed-size — Once they're created, we can't change their size.
    • Homogenous — All of the elements in them have to be the same type.
    • Contiguous — If we looked at an array in memory, we'd see all of the elements side by side.
    • Ordered — We can talk about what the first, third, or forty-second element of the array is.
  • Arrays allow constant-time access: We can jump straight to an arbitrary element of the array.
  • In terms of object lifetime, arrays act just like individual variables. The compiler needs to know ahead of time how big the array will be, so that it can write the instructions to allocate enough space to store the array.
    • Declare and initialize an array: int arr[3]{1, 2, 3};
    • Usage: To access the item at index i: arr[i]
      • arr[i] is translated to *(arr + i)
      • *x means the value in memory at the address given by x
      • arr + i means the address at an offset of i from the address given by arr
      • So *(arr + i) means the value in memory at the address of the item at offset i from the start of the array.
    • Destruction and deallocation:
      • When the array is destroyed, each item is destroyed.
      • When the array is deallocated, all items are deallocated.
  • Accessing an array out-of-bounds causes undefined behavior.
    • Undefined behavior means your program has gone off the rails, anything could happen, from something catastrophic to everything seeming to work.
    • You should never write a program that you know has undefined behavior just because nothing bad happened when you tested it.
  • Typical C++ compilers generate code that does things the fastest and easiest way, without any special safety checks.
    • That includes finding the place in memory where we're claiming an item should be and interpreting the bits at that location as being of the appropriate type (that you asked for).
    • Accessing an array out-of-bounds can cause strange behavior. While, in principle, anything can happen when code causes undefined behavior, the strange behaviors you might see can vary between systems. But you can learn to recognize problematic behaviors, especially on the systems you use for coding and testing.
  • Accessing memory that is way out-of-bounds can cause your program to crash.
    • The operating system will not allow your program to access memory outside of its allotted region.
    • This error is called a segmentation fault (segfault for short).

Code Style

  • The goal of our code should always be to explain our thinking to other people who read the code.
  • Similar things should look similar and different things should look different.

Testing

  • When we write tests for our code, our goal should be to reveal bugs, not just demonstrate that our code "works".
  • When you write tests, think about what edge cases you need to consider to make sure that your implementation is correct.
  • If you make a mistake in your own code that results in "wrong" behavior, write a test for it! While we encourage test-first development, you can always add to your tests to make them more thorough as you develop a deeper understanding of where the tricky parts are in a particular coding task.

(When logged in, completion status appears here.)