In C/C++, the main function receives parameters which are of type char*
.
int main(int argc, char* argv[]){
return 0;
}
Usually it is unknown where they are.
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char **foo;
char *bar[] = {"foo", "bar"};
(void)argv; /* avoid unused argv warning */
foo = malloc(sizeof *foo);
foo[0] = malloc(42);
strcpy(foo[0], "forty two");
/* where is foo located? stack? heap? somewhere else? */
if (argc != 42) main(42, foo); else return 0;
/* where is bar located? stack? heap? somewhere else? */
if (argc != 43) main(43, bar); else return 0;
/* except for the fact that bar elements
** point to unmodifiable strings
** this call to main is perfectably reasonable */
return 0;
/* please ignore memory leaks, thank you */
}
As pmg
mentions, when main
is called recursively, it's up to the caller where the arguments point to. Basically the answer is the same on the original invocation of main
, except that the "caller" is the C implementation/OS.
On UNIX-y systems, the strings that argv
points to, the argv
pointers themselves, and the process's initial environment variables are almost always stored at the very top of the stack.
As many other answers here point out, the precise mechanism a compiler implementation uses to pass arguments to main is unspecified by the standard (as is the mechanism a compiler uses to pass any arguments to a function). Strictly speaking, the compiler need not even pass anything useful in those parameters, since the values are implementation-defined. But neither of these are particularly helpful answers.
The typical C (or C++) program is compiled for what's known as a 'hosted' execution environment (using function main()
as the starting point of your program is one of the requirements for a hosted environment). The key thing to know is that the compiler arranges things so that when the executable is launched by the operating system, the compiler's runtime gets control initially - not the main()
function. The runtime's initialization code performs whatever initialization is necessary, including allocating memory for the arguments to main()
, then it transfers control to main()
.
The memory for the arguments to main()
could come from the heap, could be allocated on the stack (possibly using techniques that aren't available to standard C code), or could use statically allocated memory, though that's a less likely option just because it's less flexible. The standard does require that the memory used for the strings pointed to by argv
are modifiable and that modifications made to those string persist throughout the program's lifetime.
Just be aware that before execution reaches main()
, quite a bit of code has already been run that's setting up the environment for your program to run in.
It's actually a combination of compiler dependence and operating system dependence. main()
is a function just like any other C function, so the location of the two parameters argc
and argv
will follow standard for the compiler on the platform. e.g. for most C compilers targeting x86 they will be on the stack just above the return address and the saved base pointer (the stack grows downwards, remember). On x86_64 parameters are passed in registers, so argc
will be in %edi
and argv
will be in %rsi
. Code in the main function generated by the compiler then copies them to the stack, and that is where later references point. This is so the registers can be used for function calls from main
.
The block of char*
s that argv points to and the actual sequences of characters could be anywhere. They will start in some operating system defined location and may be copied by the pre-amble code that the linker generates to the stack or somewhere else. You'll have to look at the code for exec()
and the assembler pre-amble generated by the linker to find out.