I recently wrote my first C program: a simple number-guessing game. I have some experience with Python, so loops and conditionals were familiar, but I'm still learning how C handles variables and program startup.
In the original version, I declared the random number outside main():
int num = rand() % 100 + 1;
My compiler rejected this, and I was told to move the declaration inside main(). I don't understand why calling rand() is allowed inside main() but not when initializing a global variable. Could someone explain this in simple terms? I'd also appreciate any other beginner-friendly suggestions about the program.
3 Answers
The compiler is not executing your whole program to create the initial global memory. It prepares that memory as part of building and loading the executable, so it can fill it with fixed values such as 10, 3 + 4, or a constant macro. It cannot run an arbitrary function like rand() during that step.
One more improvement would be to check the return value of scanf(). If the user enters text instead of an integer, scanf("%d", &x) fails and the input can cause the loop to behave badly. For a first program, though, the overall control flow is a perfectly reasonable start.
Moving num into main() is also a good design choice because the number is only needed by that game. A global variable can be accessed throughout the program, which makes larger programs harder to understand and easier to accidentally change. Keeping data local makes functions more self-contained.
Also, rand() normally produces the same sequence each time the program runs unless you seed it, commonly with something based on the current time. For example, you might call srand((unsigned)time(NULL)); after including
At file scope, a variable such as num has static storage duration. Its initial value has to be worked out before main() starts, and C requires that initializer to be a constant expression—something the compiler can determine while building the program. rand() is a function that only produces a value while the program is running, so it cannot be used there.
Inside main(), execution has started, so C can call rand() and then assign the result:
int main(void) {
int num = rand() % 100 + 1;
/* ... */
}
The same issue would apply to using the current time: the compiler cannot know what the time will be when someone eventually runs the program.

That makes sense. So the important distinction is that the global initializer is handled before normal program execution, while the local initializer runs as part of main().