How does srand relate to rand function?

Solution 1:

The random number seed is a global static variable. rand and srand both have access to it.

Solution 2:

srand() sets the seed which is used by rand to generate "random" numbers (in quotes because they're generally pseudo-random). If you don't call srand before your first call to rand, it's as if you had called srand(1) to set the seed to one.

A lot of code uses the current time as the seed so as to make each program run use a different sequence of random numbers but you can always change that to something like srand(42) during debugging, for the purposes of repeatability. And the call to time() doesn't actually need a variable to place the time in, you can just pass NULL:

srand (time (NULL));

The whole thing could be implemented in a single file with something like the following, the example given in the standard (ISO C99 7.20.2.2 The srand function).

// RAND_MAX assumed to be 32767.
static unsigned long int next = 1;
void srand(unsigned int seed) { next = seed; }
int rand(void) {
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65536) % 32768;
}

The fact that next is a static variable at the top of the file means that it's invisible to everything outside the file but visible to everything inside (sort of a localised global). That's the communication method between srand() and rand().

Solution 3:

You don't see a link because (luckily!) whoever designed rand() decided to keep that an implementation detail, in the same way as you don't see what's inside a FILE from stdio; the downside is that they decided to make that state a global (but hidden) variable rather than a parameter to the generator.

Contrast that to the deprecated rand_r(): the state is an unsigned integer (assumed to be >= 32 bits), which means that even it's forbidden to use any better generator whose state is greater than that, simply because there is no room to store it!

By keeping the internal state hidden, instead, one is free to pick whatever algorithm works best (speed, period, ...) and use it behind the scenes, as long as you guarantee that calling rand without initialization is the same as calling srand with seed==1.

Paxdiablo showed you the example from the C standard; see eg http://en.wikipedia.org/wiki/Multiply-with-carry for an example using a different generator that you could hide behind rand/srand.

Just to be extra-extra clear: had rand_r been designed properly, there would be an opaque type, say rand_t (which could be an integer, a structure, an array, ...), which you would pass to rand_r and to some hypotetical srand_r, as in

rand_t state;
srand_r(&state, 1);
n = rand_r(&state);

The rand function is exactly like this, except that there's only one state variable.