I extract some interesting slides of this topic:
The memory is a very large array of bytes, each with an address. Regardless of the machine word size, there are one address per byte in the memory.
Every machine has a word size. It is usually the nominal size of integer-valued data and the size of integers for memory addressing (pointers). So, The addressing capacity in a machine depends on its word size.
To address a word in memory the address of its first byte is used.
Addresses and pointers
Pointer is a data object that contains an address (location in memory).
How should bytes within multi-byte word be ordered in memory? Response: Endianness (big endian vs. little endian).
Manipulating data in memory using C
We can do arithmetic on pointers: ptr= ptr + 1;
The sentence adds 4 (the type of ptr is int* and an int uses 4 bytes)
Pointer arithmetic can be used for array indexing in C (if pointer and array have the same type, of course). In general: &array[i] is the same as (array + i), which implicitly computes: &array + i*sizeof(array);
Assignment in C
Left-hand-side (LHS) must evaluate to a memory location (a variable). Right-hand-side (LHS) must evaluate to a value (could be an address)
Interesting example: *x = y; The value of y is copied to location to which x points.
Finally, a good practical slide on how to show the data representation of our data in memory:
Boolean bit-level operations in C
What caught my attention of this part was the sets representation: