Pointers are for all intents and purposes just memory addresses - a pointer variable is a variable that contains the ADDRESS of some data of some sort (and a double pointer, e.g. int **pp is a pointer containing the address of a pointer).

The best way to understand memory addresses and how they relate to the data is to think of memory as a large number of safety-deposit-boxes in a bank. Each box has a number, and each box can contain a number. That number can represent your age, a letter ('A', 'M' or 'z' for example), a specific card in a deck or cards, or anything else that can be represented as a number. One thing that it can represent is the number of anothe deposit box. Say we have a pointer stored in deposit box 123 - the box contains 33. In box 33 we have our "value", e.g. the value 68. So the value of the pointer itself is 33, the value that the pointer points at is 68.

Of course, computer memory has a HUGE number of "boxes", but it's the same principle.

As for binary (I'll get to hex in a bit). Binary is the same as "base 2". We usually use base 10 (also known as the "decimal" base), which has to do with the number of fingers we have on two hands. It makes for an easy way to calculate things for us humans. The problem with base 10 if you wanted to build a computer that uses it is that you'd have to have 10 different electrical levels, that can be combined with another 10 different electrical levels. Not only is this difficult to make safe against noise (a small variation may change a 7 into a 6 or an 8), but also it makes for a large number of permutations: each of the basic math operations have 100 different "single digit" solutions: 0+0 => 0, 0+1=>1, 0+2=>2, ... 1+0=>1, ... 9+9=>18. So the computer people took a much simpler form: binary, where a single digit has the only possible values of 0 and 1. Adding with only two different values on each side makes 4 different possible solutions, and we have only two different levels to track and differentiate - much easier to design something with these simple rules - ok, so you need LOTS of "Bits" (binary digits) to make some useful calcuation - rough estimate is 3 times as many bits as digits, so a 10 digit number requires about 30 bits. Anumber between 0..999 required 10 bits to be described (2 multiplied by 2 ten times over makes 1024, so we can fit 999 just below that).

To convert a decimal number to binary, we use this method:

Code:

we have an integer n that is a number we want to form into b as binary.
start at rightmost position in b.
do {
if (n is odd) output 1 else output 0
move one position to left in b.
divide n by 2
} while (n is not zero)

To convert the other way:

Code:

we have a binary number b, to convert to integer n
start at rightmost point in b
n = 0
x = 1
do {
pick current bit in b
if (bit is 1) {
add x to n;
}
multiply x by 2
} while (more in b)

Hex is using base 16. It means that each number has 16 different values, 0..15, but since we don't have 16 different symbols to describe such numbers, someone came up with the idea to pad ABCDEF onto the existing 0..9 sequence. So a hex number could be 0012 or 01FC for example. Just like each digit adds 10 times as you go left in a decimal number, a hex number is 16 times bigger each time. So 10 hex is 16 decimal. hex 10 times hex 10 is 100 hex, which is 16 * 16 => 256 decimal. 100 times 100 hex is 10000, which is 256 * 256 => 65536 decimal.

Why would anyone want to use hex? Well, the simple answer is that it's darn difficult to read and write binary numbers - they get long very quickly, a 4 digit decimal number is 12 or so digits long in binary. But converting decimal to binary or the other way around is also a bit complicated, as shown above. You would probably not easily convert 0001001001100111 into very 4711 quickly (check it if you like, but bear in mind that I just wrote it down without using a calculator).

Hex, on the other hand, because it's base is 2 * 2 * 2 * 2 => 16, is easily "mapped" into binary or the other way around. Each set of four binary digits correspond to a single hex digit as follows:

with decimal representation in parenthesis when it's not the same):

Code:

0 = 0000
1 = 0001
2 = 0010
3 = 0011
4 = 0100
5 = 0101
6 = 0110
7 = 0111
8 = 1000
9 = 1001
A = 1010 (10)
B = 1011 (11)
C = 1100 (12)
D = 1101 (13)
E = 1110 (14)
F = 1111 (15)

So if we have the number 110110 we split it into portions of 4 digits: 0011 0110 (filling with zeros at the left as needed), and then just translate from the table above: 36 hex.

I hope this helps.

Books that describe computer and processor architectures will help you further - I don't know of a particular book to recommend tho', as most of mine are one or both of:

1. packed away in the loft.

2. old and replaced by newer versions and titles.

--

Mats