All computer storage can be sub-divided into two categories. There is either a single or multiple values. Most programming languages gloss over this and present the ability to make complex structures, but at the most basic level, there is either one or more values. This is simply a fact of how memory is handled within computers. There is either a single value or a sequence of them.
The earliest form of multiple values is a concept called an array. It exists alongside the the earliest high-level programming languages like FORTRAN (1957), Lisp (1958), COBOL (1960), and ALGOL 60 (1960). Yet, while these understood arrays, the programming language C (1972) standardized how they were understand grammatically, and whose forms continue into programming languages decades later. The ancestry, like Greek to Roman in spoken languages, saw the form first arise in ALGOL 58 (1958), but was standardized through C (1972), its grandchild and much more well-known language for influence on its vast progeny.
Arrays as written in the C-family of programming languages are important because they visually differentiate something many earlier programming languages did not: semantically-encoded hardware abstraction. Arrays are sequences of values where the position of one value to the next is important. Yet, how they are implicitly encoded in the C-family of languages created something lasting: abstraction of rather than explicit expression of magnetic tape.

Invented in the 1940s and used with computers starting in the 1950s, magnetic tape is a way of using chemicals trapped between layers of plastic. When exposed to a electric charge, the tape can retain charge within part of its structure. This allows for retaining multiple electric charges over time. Through reading these saved charges, an access device can read or write to the tape through changing the charge exposed to the tap itself. One of the reasons for its longevity has to do with how it is constructed: blocks are attached together in sequence.
Due to their similar physicality, it can be helpful to think about magnetic tape like film. Each “frame” is separated from the next, and when run in sequence, they create a more complex picture than any one individually. However, while film is created to be viewed by human audiences, magnetic tape is not. Each “frame” is a block of data that is read and written by devices that examine or replace the charge on the tape. As it is processed, it is run in loops and its “frames” are treated as part of a larger abstraction of “memory” to the computer accessing it. The entire length is part of what the computer and users thinks of as a linear sequence of data. Even though the tape is in a loop, it is understood through its linearity, as if the tape was, itself, rolled out from end to end.
Computer memory is measured starting from zero. The first position is the zero position and the next is the first. A concept called a pointer is used to understand the distance between one position and the next. In programming terms, a pointer “points” to a location. It is an address of where to find data. It “points” to the location of where to find something. Since, to a computer, all software is part of its “memory,” pointers serve an important function to help direct to a new place to examine. It tells the computer where to find what it needs next.
Since a loop of magnetic tape is a long length of memory, pointers serve as a way to “jump” to a new part. If the computer is accessing one part and it finds a pointer, it follows this and moves to a different one. The pointer acts as forwarding instruction, telling the computer to “jump” to a new section and then continue what it was doing. As it understands pointers, computers treat them as a way to navigate the long length of its memory. While it does access memory in sequence, from one block to another, pointers serve as a way to move around the entirety of memory without needing to move through everything until it reaches what it needs. Instead, and as abstracted through software, the physical tape itself is moved to the needed location. The computer tells the device accessing the tape it needs a certain address and the tape is re-winded or fast-forwarded until it reaches this new location. Then, the data is examine or overwritten.
int example [ 10 ];
The programming languages symbolically encode memory access as part of their grammars. To create an array, opening and square brackets are used. They wrap, when an array is created, its length. This tells the programming language, and ultimately, the computer, how much memory is needed as part of its type. As all memory is finite, the computer needs to know how much space a potential value might take up. It does this through using the value’s data type. In programming terms, different kinds of data, for example, whole or decimal numbers, have different space requirements. The type of some data tells the computer to reserve a certain amount of space for working with the value in the future.
When used with an array, the computer reserves not only the space for one value, but for the total length of the array. This is potentially a large amount of memory reserved for working with multiple values. To help with this, a computer breaks up memory into a long sequence. It starts with the zero position and then each progressive part of the sequence can be accessed. The computer does this through creating a pointer to the first (zero) value of the sequence internally. It does not need to know where all of the values within the sequence are as long as it knows where to find the beginning value and how many are part of the sequence.
example[1] = 1;
In the C-family of programming languages, values in arrays are accessed through using square brackets after the name of the variable with a number within them. This is called its index. Internally, the computer knows where to find the first value of the sequence through its pointer. To the find any value in sequence after the first one, it performs some mathematics. It multiplies the index provided by the size of the type of the data stored. As the type was used to reserve the sequence of data, the size of all of the entries is the same. Any one position can then be accessed through using this size and multiplying it by any number less than the total length of the array. The index multiplied by the size is added to the pointer. This is the next location to access the data.
As better recording mediums were invented, the concepts were carried over. As computer storage moved from primarily magnetic tape to hard drives, the central metaphors remained. Memory is still considered as a length of blocks arranged in a linear sequence. The accessing device understands the physical distance between blocks, if there is one, and translates each “frame” of data for the computer, accessing them as requested. With hard drives, instead of viewing the “side” of the tape, it is rotated 90-degrees. The “top” of the structure is viewed and smaller blocks are used. Stacking these vertically, multiple tracks can be accessed and used at the same time. This is the same idea of using magnetic tape, but translated into three dimensions through reading multiple “tapes” at the same time to create the illusion of a unified sequence for the computer.
Outside of special circumstances, computer memory is no longer primarily magnetic tape. Various improves to hard drives have been invented and refined. Storage has grown by orders of magnitude since the invention of magnetic tape in the 1940s. However, the concepts remain in programming languages. What was first introduced with the programming language C has been encoded into other programming languages which have, themselves, been the foundations for other programming languages.
Arrays continue to be thought of as blocks of data, as computer memory continues to be represented in such models. Yet, their symbolic representations are the same as they were when considering magnetic tapes with the invention of higher-level programming languages: bounded linear sequences of values. Open square bracket, data, close square bracket.