I've an issue with passing argv to a function. Basically, I want to pass &argv[1] to the function and work from that. However, I don't understand why the following does work:
void fun(char**&argv, const int& argc);
int main(int argc, char** argv)
{
fun(++argv, --argc);
return 0;
}
yet the following doesn't work:
void fun(char**&argv, const int& argc);
int main(int argc, char** argv)
{
fun(&argv[1], --argc);
return 0;
}
Prototype:
void myfunc (char **argv, int argc)
Example usage:
myfunc (argv, argc)
If you wanted to pass ONLY one string (argv[1]):
void myfunc (char *arg, int argc)
...
myfunc (argv[1], argc)
And if you wanted to pass an array of strings starting at argv[1]:
void myfunc (char **arg, int argc)
...
myfunc (&argv[1], argc)
The error I get when I try this is that argv[1] is a temporary value and you can't assign that to a non-const reference. If you instead do this:
void fun( char** const&argv, const int& argc);
Then either ++argv or &argv[1] will work.
Obviously, if you planned to actually change the value of argv itself, this won't work, but I presume that you aren't planning to do this since you're not passing a reference to argv itself but rather to the memory location of the second entry in argv.
The reason that the first one works and the second doesn't is that the ++ operator at the front modifies the variable and then returns not just its value after the modification, but the variable itself. As a result, the variable can then be passed into fun as a reference. But the &argv[1] is just the value of a memory location. It's a computed value, not a variable in its own right, so it can't be passed in as a non-const reference.
If you're planning to try to change the value of argv itself (to point it to a different array of character arrays), then &argv[1] doesn't work for that anyway, since it's not argv. ++argv, however, is argv, just after it's had its value adjusted.
You could also handle all of this without references at all, which would make things much easier, but that's up to you. If it were my code, though, I wouldn't be using references here. The const reference to an int could just be passed by value (which would be easier) and passing a reference to a double pointer doesn't save you any null checking (as it could still well be null). So there isn't much point to it. But if you like your code to be complex, feel free.
Related
I have a bluez header file get_opt.h where argv is an argument:
extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,.....
which requires char* const* for argv. Because the unit is called from a different file I was trying to emulate argv but whatever permutation of declaring char, const and * is used I get unqualified-id or the compiler moans about not converting to char* const*. I can get const char * easily, of course. char const * argv = "0"; compiles OK in Netbeans with C++14 but
char * const * argv = "0";
produces
"error: cannot convert 'const char *' to 'char * const *'" in initialisation (sic).
How do you declare char* const* or am I mixing C with C++ so I'm up the wrong tree?
Let's review the pointer declarations:
char * -- mutable pointer to mutable data.
char const * -- mutable pointer to constant data.
char * const -- constant pointer to mutable data.
char const * const -- constant pointer to constant data.
Read pointer declarations from right to left.
Looking at the descriptions, which kind of pointer do you want?
Because void main(void) is in a different file I was trying to emulate
argv
void main(void) is not the correct main function declaration. The main function has to have int return value.
Simply change the void main(void) to int main(int argc, char **argv) in that "other" file.
It does not require char const * to be passed to. Do not change the type of the main function arguments.
int getopt_long (int ___argc, char * const *___argv);
int main(int argc, char **argv)
{
printf("%d\n", getopt_long(argc, argv));
}
Both language compile fine:
https://godbolt.org/z/5To5T931j
Credit #JaMiT above
[I don't know how to accept a commment]
Also, you might want to notice how you can remove the call to getopt_long() from that example while retaining the error (it's motivation for your declaration, but not the source of your issue). If you think about your presentation enough, you might realize that your question is not how to declare a char* const* but how to initialize it. Due to arrays decaying to a pointer, you could declare an array of pointers (char* const argv[]) instead of a pointer to pointer (char* const * argv). See The 1D array of pointers way portion of A: 2D Pointer initialization for how to initialize such a beast. Beware: given your setup, the "2D array way" from that answer is not an option. Reminder: The last pointer in the argument vector is null; argv[argc] == nullptr when those values are provided by the system to main().
This question already has answers here:
Defining own main functions arguments argc and argv
(6 answers)
Closed 6 years ago.
Hi very newbie question but I just can't figure it out:
I have a function named bar
class foo
{
public:
bool bar(int argc, char** argv);
}
argv is supposed to contain
"--dir" and "/some_path/"
How do I create argv and argc so that I can pass them into bar() ? I've tried many ways but I just can't get pointer and type conversion right.
So instead of getting argv from command line, I want to create it in the code.
Thank you for any input!
My favourite way is like this:
std::vector<std::string> arguments = {"--dir", "/some_path"};
std::vector<char*> argv;
for (const auto& arg : arguments)
argv.push_back((char*)arg.data());
argv.push_back(nullptr);
f.bar(argv.size() - 1, argv.data());
Note, that if arguments are static and do not change, then this is a little bit overkill. But this approach has advantage of being RAII compliant. It manages memory for you and deletes objects at right moment. So if argument list is dynamic, then it is the cleanest way.
Beside that, this code technically is UB if f.bar modifies data in argv array. Usually this is not the case.
Assuming you want argc and argv in the same format that are passed to main, you can call it like this:
foo f;
char *args[] = {
(char*)"--dir",
(char*)"/some_path/",
NULL
};
f.bar(2, args);
(note: this assumes bar won't modify the argument strings - in which case you should change the argument type to const char ** instead of char **)
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.
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.