Memory in a computer is just a sequential set of "buckets" that can contain numbers, characters, or boolean values. By using several buckets in a row, we get arrays. By giving names to a set of contiguous buckets, we get a "structure". But at its core, a computer memory is a very simple list of numbers. Everything else must be built up upon this.
Memory is laid out in sequential order basically from 0 on up (one byte at a time). Each position in memory has a number (called its address!).
The compiler (or interpreter) associates your variable names with memory addresses.
In some languages like C, you can actually ask the computer for the address of a variable in memory. In C this is done using the ampersand &
In many languages, the actual address is hidden from you and is of little use to you, as all the access methods "abstract" the details of the computer hardware away, allowing the programmer to concentrate on the algorithm, and not the details.
Arrays variables simply contain the address of the first element of the array. Arrays are zero based so the address simply becomes the base address plus the index.
Structure variables simply contain the address of the first element of the structure, and each "named" field of the structure forms an offset from the first bucket. The computer keeps track of this offset so that the programmer can use symbolic names instead of numbers.
Memory buckets are 8 bits long (or one byte). A character (char) is one byte. An integer is (usually) four bytes. A float is four bytes. A double is 8 bytes.
Computer address start at 0 and work their way up. Traditionally programmers refer to memory addresses (when they had to at all) using their HEXADECIMAL value. (Remember Hexadecimal is merely another way to write numbers, the same as Roman numerals, such as X meaning ten, and XIV meaning 14. In Hex (Base 16) the digits go from 1 to fifteen, but we abbreviate 10,11,12,13,14, and 15, as A,B,C,D,E,F. Then we use powers of 16. Thus in base 10, 99 is 9 * 10 + 9 * 1, ff in hex is 15*16 + 15*1)
Memory Computer Address Variable Name |-------| | | 0 |-------| | | 1 |-------| | | 2 |-------| | | 3 |-------| | | 4 |-------| | | 5 |-------| | | 6 |-------| | | 7 |-------| | | 8 |-------| ... |-------| | | 0x11cedf bool is_jim_smart; |-------| | | 0x11cee0 char jims_initial; |-------| | | 0x11cee1 int jims_age; (also uses the next 3 bytes) |-------| | | 0x11cee2 |-------| | | 0x11cee3 |-------| | | 0x11cee4 |-------| | | 0x11cee5 float jims_height; (also uses the next 3 bytes) |-------| | | 0x11cee6 |-------| | | 0x11cee7 |-------| | | 0x11cee8 |-------| ...
As mentioned, the C programming language gives the programmer much more "low level" access to memory. This (sometimes) allows for "faster and more efficient code", but if offset by the increased likelihood of errors. Below is some C code to print the actual addresses in memory for some variables.
Please note: I would argue that it is unclear what having access to actual memory addresses buys most programmers, but this is a feature of the language, and if you were writing an operating system or advanced Computer Science project, you may well need it. If you are writing a Mechanical or Civil (etc) Engineering simulation of a bridge, etc, you absolutely do not need access to this type of information.
printf("is_jim_smart address is (in decimal %d), (in hex %x)\n", & is_jim_smart, & is_jim_smart);
printf("jims_age address is (in decimal %d), (in hex %x)\n", & jims_age, & jims_age);
is_jim_smart address is (in decimal 1167071), (in hex 0x11cedf)
jims_age address is (in decimal 1167073), (in hex 0x11cee1)