This question already has answers here:
Declaring pointers; asterisk on the left or right of the space between the type and name? [duplicate]
(6 answers)
Closed 1 year ago.
I have the two following C++ main function headers:
int main(int argc, char **argv)
int main(int argc, char** argv)
I know that the asterisk * signifies a pointer, but I do not understand the difference between these two. The one I usually see is char **argv, which, If I'm not mistaken, declares argv to be a pointer to a pointer to a char. If so, then what is char** argv?
If so, then what is char** argv?
If (also) declares argv to be a pointer to a pointer to a char.
What is the difference between char **argv and char** argv?
The difference between them is the placement of space. There is no other difference. These are also the same:
char**argv
char * * argv
char
*
*
argv
Related
This question already has answers here:
C++ : Meaning of const char*const*
(5 answers)
Closed 6 years ago.
I'm working on simulating computer networks using "NS2 Simulator". I don't really understand why we should use const char* const* argv instead of char *?
Can I use char * instead of that? There are many QA about this subject but I've confused about that. Don't mark this question as "Duplicate", please .
why we use const char* const* argv in the function below? is this a rule in c++ standard? can i use either string or char ** instead of that?
Function Connector::command.
//~ns/common/connector.cc
int Connector::command(int argc, const char*const* argv)
{
Tcl& tcl = Tcl::instance();
...
if (argc == 3) {
if (strcmp(argv[1], "target") == 0) {
...
target_ = (NsObject*)TclObject::lookup(argv[2]);
...
}
...
}
return (NsObject::command(argc, argv));
}
const char*const* argv means "pointer to constant pointer to constant char". It's not the same as char*. There is a reason for the const modifier, as the argv pointer wont be reassigned, the elements will have to be accessed by subscript.
This makes it safe for the caller to dynamically allocate argv, pass it into command(), and free it later. Otherwise, if you point a pointer elsewhere before it is freed, then you've leaked the memory that it used to point to.
const char* const* argv creates two levels of indirection - first level is a const pointer to a const char, and second level is a pointer to the const pointer.
The programmer is allowed to const qualify arguments how they see fit. The benefit of this signature:
void func(const char* const* argv);
...is that it will accept argument arrays (of the type passed to main() or exec()), with any const qualification.
So all these are acceptable:
int main(int, char** argv)
{
func(argv);
}
int main(int, const char** argv)
{
func(argv);
}
int main(int, char* const* argv)
{
func(argv);
}
int main(int, const char* const* argv)
{
func(argv);
}
So if you are writing a function to accept argument array parameters (that your function will not modify) then its probably the best signature to select.
why we should use "const ... argv" instead of "char *" ?
The 'const' is from you, the programmer, commanding the compiler to inform you when the code you write tries to modify argv.
can i use char * instead of that?
Possibly, and sometimes it does not matter. But if you mistakenly modify argv (or whatever the const var name is), then the compiler won't let you know you made a mistake, and the result may be something you do not want, even UB.
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.
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)
...
}
the following does not compile:
int main (int argc, char *argv[]) {
char arr[2][2];
char **ptr = arr;
return 0;
}
Yet the following does:
int main (int argc, char *argv[]) {
char **ptr = argv;
return 0;
}
Thus I would conclude that argv is not a c style array which is stored as a single block of memory but rather is some sort of pointer array. Can somebody confirm that?
Thank you and Regards.
That's correct, argv is a pointer to the first element of an array of pointers, each of which in turn (except for the last one) is a pointer to the first character in a string of characters giving the respective command line argument.
Function parameters cannot be arrays.
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.