I am clear about the difference between char* argv[] and char** argv (as explained, for instance, in this question).
But what kind of type is char** argv[] ? A pointer to a pointer to a pointer of chars? And what would that be, when used to pass arguments to the program?
For the record, the type occurs in the following declaration of a C++ library I am trying to interface to Python:
/** Initialize the Stage library. Stage will parse the argument
array looking for parameters in the conventional way. */
void Init( int* argc, char** argv[] );
If main definition is main(int argc, char * argv[]) and you want to send argv via pointer, you will do Init( &argc, &argv ). And the corresponding parameter can be char ** argv[].
I assume that this Init function will make changes to the argc and argv that main has received, so it needs pointers to them.
If the library uses some program arguments, the Init function can handle them, and then remove those arguments from the argument list before it is processed by the rest of the program.
char** argv[] is an array of char**, IOW an array of pointers to pointers to chars, or more likely an array of pointers to null-terminated character strings, eg:
char *str1 = "...";
char *str2 = "....";
char** argv[2];
argv[0] = &str1;
argv[1] = &str2;
However, if argv is coming from main() itself, then char** is a typo, it must be char* instead:
char* argv[]
But if argv is coming from some library instead, it very well could be wrapping the original argv array from main() inside its own array, in which case char**[] might make sense so it can point at the original strings and not have to copy them.
Related
In many C++ IDE's and compilers, when it generates the main function for you, it looks like this:
int main(int argc, char *argv[])
When I code C++ without an IDE, just with a command line compiler, I type:
int main()
without any parameters. What does this mean, and is it vital to my program?
argv and argc are how command line arguments are passed to main() in C and C++.
argc will be the number of strings pointed to by argv. This will (in practice) be 1 plus the number of arguments, as virtually all implementations will prepend the name of the program to the array.
The variables are named argc (argument count) and argv (argument vector) by convention, but they can be given any valid identifier: int main(int num_args, char** arg_strings) is equally valid.
They can also be omitted entirely, yielding int main(), if you do not intend to process command line arguments.
Try the following program:
#include <iostream>
int main(int argc, char** argv) {
std::cout << "Have " << argc << " arguments:" << std::endl;
for (int i = 0; i < argc; ++i) {
std::cout << argv[i] << std::endl;
}
}
Running it with ./test a1 b2 c3 will output
Have 4 arguments:
./test
a1
b2
c3
argc is the number of arguments being passed into your program from the command line and argv is the array of arguments.
You can loop through the arguments knowing the number of them like:
for(int i = 0; i < argc; i++)
{
// argv[i] is the argument at index i
}
Suppose you run your program thus (using sh syntax):
myprog arg1 arg2 'arg 3'
If you declared your main as int main(int argc, char *argv[]), then (in most environments), your main() will be called as if like:
p = { "myprog", "arg1", "arg2", "arg 3", NULL };
exit(main(4, p));
However, if you declared your main as int main(), it will be called something like
exit(main());
and you don't get the arguments passed.
Two additional things to note:
These are the only two standard-mandated signatures for main. If a particular platform accepts extra arguments or a different return type, then that's an extension and should not be relied upon in a portable program.
*argv[] and **argv are exactly equivalent, so you can write int main(int argc, char *argv[]) as int main(int argc, char **argv).
int main();
This is a simple declaration. It cannot take any command line arguments.
int main(int argc, char* argv[]);
This declaration is used when your program must take command-line arguments. When run like such:
myprogram arg1 arg2 arg3
argc, or Argument Count, will be set to 4 (four arguments), and argv, or Argument Vectors, will be populated with string pointers to "myprogram", "arg1", "arg2", and "arg3". The program invocation (myprogram) is included in the arguments!
Alternatively, you could use:
int main(int argc, char** argv);
This is also valid.
There is another parameter you can add:
int main (int argc, char *argv[], char *envp[])
The envp parameter also contains environment variables. Each entry follows this format:
VARIABLENAME=VariableValue
like this:
SHELL=/bin/bash
The environment variables list is null-terminated.
IMPORTANT: DO NOT use any argv or envp values directly in calls to system()! This is a huge security hole as malicious users could set environment variables to command-line commands and (potentially) cause massive damage. In general, just don't use system(). There is almost always a better solution implemented through C libraries.
The parameters to main represent the command line parameters provided to the program when it was started. The argc parameter represents the number of command line arguments, and char *argv[] is an array of strings (character pointers) representing the individual arguments provided on the command line.
The main function can have two parameters, argc and argv. argc is an integer (int) parameter, and it is the number of arguments passed to the program.
The program name is always the first argument, so there will be at least one argument to a program and the minimum value of argc will be one. But if a program has itself two arguments the value of argc will be three.
Parameter argv points to a string array and is called the argument vector. It is a one dimensional string array of function arguments.
Lets 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). A diagram is given for illustration purposes:
As already said in other answers, this form of declaration of main is used when we want to make use of the command line argument(s).
The first parameter is the number of arguments provided and the second parameter is a list of strings representing those arguments.
Both of
int main(int argc, char *argv[]);
int main();
are legal definitions of the entry point for a C or C++ program. Stroustrup: C++ Style and Technique FAQ details some of the variations that are possible or legal for your main function.
In case you learn something from this
#include<iostream>
using namespace std;
int main(int argc, char** argv) {
cout << "This program has " << argc << " arguments:" << endl;
for (int i = 0; i < argc; ++i) {
cout << argv[i] << endl;
}
return 0;
}
This program has 3 arguments. Then the output will be like this.
C:\Users\user\Desktop\hello.exe
hello
people
When using int and char**, the first argument will be the number of commands in by which the programs is called and second one is all those commands
Just to add because someone says there is a third parameter (*envp[]), it's true, there is, but is not POSIX safe, if you want your program to use environment variables you should use extern char environ ;D
In c++ I've got a main function with
int argc, char * argv[]
I need to access the data in argv[] (i.e the arguments) in another function.
I am going to declare a global variable, a pointer to the char **argv.
How do I do this?
In C++, usually* the best way to handle argv is this:
int main(int argc, char **argv)
{
std::vector<std::string> args(argv, argv + argc);
}
Now you have args, a correctly constructed std::vector holding each element of argv as a std::string. No ugly C-style const char* in sight.
Then you can just pass this vector or some of its elements as you need.
* It carries the memory & time overhead of dynamically allocating one copy of each argv string. But for the vast majority of programs, command-line handling is not performance-critical and the increased maintainability and robustness is well worth it.
Global variables should be avoided and you should prefer passing arguments. Anyway, you can just use:
char **global_argv = NULL;
int main(int argc, char * argv[]){
...
global_argv = argv;
...
}
A better way would be:
void my_fun1(int argc, char **argv); // Passing all the program arguments
void my_fun2(char *arg); // Passing just the one you need
int main(int argc, char * argv[]){
...
my_fun1(argc, argv);
my_fun2(argv[3]); // Supposing you need the 3rd parameter (fourth on argv)
...
}
could you please help me understand this.
I have function that needs "char ***argv";
As far as I understand it's :
pointer to pointer to array of char pointers.
something like this: "char *arr[]" ?
char xx1 = '1';
char xx2 = '2';
char *argv[] = {&xx1,&xx2};
Then I call my function with gtk_init (&argc, &argv);
And get error:
main.cpp:43:31: error: cannot convert ‘char* (*)[2]’ to ‘char***’ for argument ‘2’ to ‘void gtk_init(int*, char***)’
Thank you for any help.
A char*** is a "pointer to pointer to pointer to char". No arrays involved at all. Your argv is an "array of 2 pointer to char". The name of your array, argv, will decay to a pointer to its first element in certain circumstances - this pointer will have type char**, or "pointer to pointer to char".
When you do &argv, you get a char* (*)[2], or a "pointer to array of 2 pointer to char". Which is not what you want. That's because you're taking the address of an array, not of a pointer.
Also, you're going to have a problem with the fact that you're pointers in argv are just pointing at single chars, not at null-terminated strings. gtk_init will almost certainly be expecting null-terminated strings.
So what you can you do? Try this:
char xx1[] = "1"; // Now these are null-terminated strings
char xx2[] = "2";
char* argv[] = {xx1, xx2};
char** argvp = argv; // Use the fact that the array will decay
gtk_init(&argc, &argv); // &argv will now be a char***
The reason for using arrays for the strings is because we need the chars to be non-const, but a char* str = "hello"; style declaration is deprecated - it must be const char*. However, by using arrays, the contents of the string literal are copied into our array, so we can freely make it non-const.
gtk_init really just expects you to pass the argc and argv parameters of your main function to it like so:
int main(int argc, char* argv[])
{
gtk_init(&argc, &argv);
// ...
}
You may now ask "But why is &argv now allowed? argv is the same type as in the question! Why don't we get a pointer to array again?" Actually, argv is not the same type, despite how much it looks like it is. When you define a function that takes an array argument, it actually gets transformed to a pointer. So the definition of main is equivalent to:
int main(int argc, char** argv);
So when we do &argv, we're totally fine, because it gives us a char***.
As #OmnipotentEntity says in the comments - you'd better have a good excuse for not passing the parameters of main to gtk_init.
I'm making the assumption that the array of strings passed into the main function as argv in void main( int argc, char* argv[] ) remains in scope for the duration of the application.
My question is therefore whether it is possible, using boost::program_options to get a pointer to the actual element in argv which represents a particular option.
That is, rather than allocating a std::string when parsing, it is possible to just get a pointer to the start of a string option value.
In many C++ IDE's and compilers, when it generates the main function for you, it looks like this:
int main(int argc, char *argv[])
When I code C++ without an IDE, just with a command line compiler, I type:
int main()
without any parameters. What does this mean, and is it vital to my program?
argv and argc are how command line arguments are passed to main() in C and C++.
argc will be the number of strings pointed to by argv. This will (in practice) be 1 plus the number of arguments, as virtually all implementations will prepend the name of the program to the array.
The variables are named argc (argument count) and argv (argument vector) by convention, but they can be given any valid identifier: int main(int num_args, char** arg_strings) is equally valid.
They can also be omitted entirely, yielding int main(), if you do not intend to process command line arguments.
Try the following program:
#include <iostream>
int main(int argc, char** argv) {
std::cout << "Have " << argc << " arguments:" << std::endl;
for (int i = 0; i < argc; ++i) {
std::cout << argv[i] << std::endl;
}
}
Running it with ./test a1 b2 c3 will output
Have 4 arguments:
./test
a1
b2
c3
argc is the number of arguments being passed into your program from the command line and argv is the array of arguments.
You can loop through the arguments knowing the number of them like:
for(int i = 0; i < argc; i++)
{
// argv[i] is the argument at index i
}
Suppose you run your program thus (using sh syntax):
myprog arg1 arg2 'arg 3'
If you declared your main as int main(int argc, char *argv[]), then (in most environments), your main() will be called as if like:
p = { "myprog", "arg1", "arg2", "arg 3", NULL };
exit(main(4, p));
However, if you declared your main as int main(), it will be called something like
exit(main());
and you don't get the arguments passed.
Two additional things to note:
These are the only two standard-mandated signatures for main. If a particular platform accepts extra arguments or a different return type, then that's an extension and should not be relied upon in a portable program.
*argv[] and **argv are exactly equivalent, so you can write int main(int argc, char *argv[]) as int main(int argc, char **argv).
int main();
This is a simple declaration. It cannot take any command line arguments.
int main(int argc, char* argv[]);
This declaration is used when your program must take command-line arguments. When run like such:
myprogram arg1 arg2 arg3
argc, or Argument Count, will be set to 4 (four arguments), and argv, or Argument Vectors, will be populated with string pointers to "myprogram", "arg1", "arg2", and "arg3". The program invocation (myprogram) is included in the arguments!
Alternatively, you could use:
int main(int argc, char** argv);
This is also valid.
There is another parameter you can add:
int main (int argc, char *argv[], char *envp[])
The envp parameter also contains environment variables. Each entry follows this format:
VARIABLENAME=VariableValue
like this:
SHELL=/bin/bash
The environment variables list is null-terminated.
IMPORTANT: DO NOT use any argv or envp values directly in calls to system()! This is a huge security hole as malicious users could set environment variables to command-line commands and (potentially) cause massive damage. In general, just don't use system(). There is almost always a better solution implemented through C libraries.
The parameters to main represent the command line parameters provided to the program when it was started. The argc parameter represents the number of command line arguments, and char *argv[] is an array of strings (character pointers) representing the individual arguments provided on the command line.
The main function can have two parameters, argc and argv. argc is an integer (int) parameter, and it is the number of arguments passed to the program.
The program name is always the first argument, so there will be at least one argument to a program and the minimum value of argc will be one. But if a program has itself two arguments the value of argc will be three.
Parameter argv points to a string array and is called the argument vector. It is a one dimensional string array of function arguments.
Lets 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). A diagram is given for illustration purposes:
As already said in other answers, this form of declaration of main is used when we want to make use of the command line argument(s).
The first parameter is the number of arguments provided and the second parameter is a list of strings representing those arguments.
Both of
int main(int argc, char *argv[]);
int main();
are legal definitions of the entry point for a C or C++ program. Stroustrup: C++ Style and Technique FAQ details some of the variations that are possible or legal for your main function.
In case you learn something from this
#include<iostream>
using namespace std;
int main(int argc, char** argv) {
cout << "This program has " << argc << " arguments:" << endl;
for (int i = 0; i < argc; ++i) {
cout << argv[i] << endl;
}
return 0;
}
This program has 3 arguments. Then the output will be like this.
C:\Users\user\Desktop\hello.exe
hello
people
When using int and char**, the first argument will be the number of commands in by which the programs is called and second one is all those commands
Just to add because someone says there is a third parameter (*envp[]), it's true, there is, but is not POSIX safe, if you want your program to use environment variables you should use extern char environ ;D