ranks+3 is not an lvalue for the same reason that 1+3 is not an lvalue; the result is simply a numerical (pointer) value, not a reference to an object.
Put another way, if the result of ranks + 3 is 0xdeadbeef, you cannot write
0xdeadbeef = 10;
for the same reason you cannot write
4 = 10;
However, *(ranks+3) is an lvalue, because you are dereferencing that pointer value; it is the 4th element of the ranks array, and is equivalent to ranks[3].
Similarly, ranks is not an lvalue except in the context of sizeof or the unary & operator. Since array expressions "decay" to pointer expressions in most contexts, you again wind up with the situation of
ranks = 10;
being equivalent to
0xdeadbeef = 10;
Again, you'd have to dereference ranks as either *ranks or ranks[0] for it to be an lvalue.