Where are C/C++ main function's parameters?
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.
The parameters of the Main function in C++
Let's see what is happening in your example on case by case basis:
Case 1
Here we consider the statement:
char* p = "Hello";
On the right hand side of the above statement, we've the string literal "Hello"
which is of type const char[6]
. There are two ways to understand why the above statement didn't work.
- In some contexts,
const char[6]
decays to aconst char*
due to type decay. This basically means that on the right hand side we will have aconst char*
while on the left hand side we have achar*
. Note also that this means that on the right hand side we've a low-level const but on the left hand side we don't have any low-level const. So, the given statement won't work. For the statement to work we've to make sure that the left hand side should've either same or greater low-level const qualifier than the right hand side.
A few example would illustrate the point:
int arr1[] = {1,2,3};
int* ptr1 = arr1; //this works because arr1 decays to int* and both sides have no low level const
const int arr2[] = {1,2,3};
int* ptr2 = arr2; //won't work, right hand side will have a low level const(as arr2 decays to const char*) while the left hand side will not have a low level const
const int* ptr3 = arr2; //this works, both side will have a low level const
- The second way(which is basically equivalent to the 1st) to understand this is that since
"Hello"
is of typeconst char[6]
, so if we are allowed to writechar* p = "Hello";
then that would mean that we're allowed to change the elements of the array. But note that the typeconst char[6]
means that thechar
elements inside the array are immutable(or non-changable). Thus, allowingchar* p = "Hello";
would allow changingconst
marked data, which should not happen(since the data was not supposed to change as it was markedconst
). So to prevent this from happening we have to useconst char* p = "Hello";
so that the pointerp
is not allowed to change theconst
marked data.
Case 2
Here we consider the declaration:
int main (int argc, char *argv[])
In the above declaration, the type of the second parameter named argv
is actually a char**
. That is, argv
is a pointer to a pointer to a char
. This is because a char* []
decays to a char**
due to type decay. For example, the below given declarations are equivalent:
int main (int argc, char *argv[]); //first declaration
int main (int argc, char **argv); //RE-DECLARATION. Equivalent to the above declaration
In other words, argv
is a pointer that points to the first element of an array with elements of type char*
. Moreover, each elements argv[i]
of the array(with elements of type char*
) itself point to a character which is the start of a null terminated character string. That is, each element argv[i]
points to the first element of an array with elements of type char
(and not const char
). Thus, there is no need for const char*
. A diagram is given for illustration purposes:
Why can C main function be coded with or without parameters?
Making it work has to do with the binary format of the executable and the OS's loader. The linker doesn't care (well it cares a little: it needs to mark the entry point) and the only caller routine is the loader.
The loader for any system must know how to bring supported binary format into memory and branch into the entry point. This varies slightly by system and binary format.
If you have a question about a particular OS/binary format, you may want to clarify.
what is the purpose of arguments in main method in C language
The signature of main is:
int main(int argc, char **argv);
Where argc
is the number of command line arguments passed in, which includes the actual name of the program, as invoked by the user.
argv
contains the actual arguments, starting with index 1, since index 0
is the program name.
So, if you run your program like this:
./program hello world
Then:
argc
would be 3
.
argv[0]
would be ./program
.
argv[1]
would be hello
.
argv[2]
would be world
.
I hope this is clear enough for you.
If you want to understand it more clearly, go to these: Link, Link
Function arguments alignment in C
&cnt
and &adr
are addresses of parameters. Parameters are variables local to the function that are initialized to the argument values passed by the caller. The compiler is not required to use the same space for parameters that is used to pass the arguments.
When an argument is passed on the stack, a compiler might or might not reuse its stack space for the parameter. When an argument is passed in a processor register and an address is needed for it, as because a program takes the address and prints it, then the compiler has to reserve space for the parameter on the stack, copy the value from the register to the stack space (as with a store instruction), and use the address of the stack space.
When the compiler is laying out stack space for this, it does not need to care that cnt
and adr
are consecutive parameters. It can organize data about all the stack space it needs—for parameters, for local variables, for the return address, for its own purposes, whatever—and then just assign stack space for those things in any order. So you should not expect there to be any close relationship between the addresses of cnt
and adr
.
(For functions with variable arguments, the compiler needs someway to implement the variable argument list features. This usually involves having the variable arguments consecutive in memory after the last fixed argument, which would be adr
in the example. This does not impose any relationship between cnt
and adr
.)
How do you pass a function as a parameter in C?
Declaration
A prototype for a function which takes a function parameter looks like the following:
void func ( void (*f)(int) );
This states that the parameter f
will be a pointer to a function which has a void
return type and which takes a single int
parameter. The following function (print
) is an example of a function which could be passed to func
as a parameter because it is the proper type:
void print ( int x ) {
printf("%d\n", x);
}
Function Call
When calling a function with a function parameter, the value passed must be a pointer to a function. Use the function's name (without parentheses) for this:
func(print);
would call func
, passing the print function to it.
Function Body
As with any parameter, func
can now use the parameter's name in the function body to access the value of the parameter. Let's say that func
will apply the function it is passed to the numbers 0-4. Consider, first, what the loop would look like to call print directly:
for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
print(ctr);
}
Since func
's parameter declaration says that f
is the name for a pointer to the desired function, we recall first that if f
is a pointer then *f
is the thing that f
points to (i.e. the function print
in this case). As a result, just replace every occurrence of print in the loop above with *f
:
void func ( void (*f)(int) ) {
for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
(*f)(ctr);
}
}
Source
How to use command line argument in function calls and parameters?
You have an array of strings in argv
that looks like this:
{ "./cnp", "cut", "13", "5", "copy", "33", "7", "paste", "1", "input-b.txt", "output.txt" }
On the assumption that the last two arguments are always the input and output files, I would loop through the arguments from 1 to arc - 3
to process the commands e.g. the below sketch is not a complete solution but should give you some ideas.
if (argc < 3)
{
// Handle the fact that there were not enough arguments.
}
else
{
int commandArgs = argc - 2;
for (int i = 1 ; i < commandArgs ; ++i) // Start at 1 to omit program name
{
if (strcmp(argv[i], "cut") == 0)
{
if (commandArgs - i < 2)
{
// Handle not enough args to cut
}
else
{
// You have a cut command, call cut or save it to call cut later
i += 2; // Skip the two parameters
}
}
else if (strcmp(argv[i], "copy") == 0)
{
// similar pattern to above
}
else if (strcmp(argv[i], "paste") == 0)
{
// similar pattern to above
}
else
{
// Handle invalid command error
}
}
}
Main function with three arguments
The third argument to main is normally called envp
.
int main(int argc, char **argv, char **envp) {
Many compilers provide a third argument to main
, but it is not specified in the C standard, so using it is undefined behaviour. If you try to port the code to a platform that doesn't provide a third parameter the program will most likely fail.
Is char *envp[] as a third argument to main() portable
Related Topics
Pimpl Idiom VS Pure Virtual Class Interface
How to Use Formatmessage() Properly in C++
Clearing Terminal in Linux with C++ Code
What Is Going on with 'Gets(Stdin)' on the Site Coderbyte
I Cannot Pass Lambda as Std::Function
Override a Member Function with Different Return Type
Are Compound Literals Standard C++
Why Is the Empty Base Class Optimization (Ebo) Is Not Working in Msvc
Can Lambda Functions Be Templated
How to Use _Crt_Secure_No_Warnings
How to Determine the Size of an Object in C++
Pure Virtual Functions May Not Have an Inline Definition. Why