There's a lot of answers here, but no-one seems to have really explained why it is that rand() always generates the same sequence given the same seed - or even what the seed is really doing. So here goes.
The rand() function maintains an internal state. Conceptually, you could think of this as a global variable of some type called rand_state. Each time you call rand(), it does two things. It uses the existing state to calculate a new state, and it uses the new state to calculate a number to return to you:
state_t rand_state = INITIAL_STATE;
state_t calculate_next_state(state_t s);
int calculate_return_value(state_t s);
int rand(void)
{
rand_state = calculate_next_state(rand_state);
return calculate_return_value(rand_state);
}
Now you can see that each time you call rand(), it's going to make rand_state move one step along a pre-determined path. The random values you see are just based on where you are along that path, so they're going to follow a pre-determined sequence too.
Now here's where srand() comes in. It lets you jump to a different point on the path:
state_t generate_random_state(unsigned int seed);
void srand(unsigned int seed)
{
rand_state = generate_random_state(seed);
}
The exact details of state_t, calculate_next_state(), calculate_return_value() and generate_random_state() can vary from platform to platform, but they're usually quite simple.
You can see from this that every time your program starts, rand_state is going to start off at INITIAL_STATE (which is equivalent to generate_random_state(1)) - which is why you always get the same sequence if you don't use srand().