create argc argv in the code [duplicate]
Asked Answered
A

2

11

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!

Abramson answered 5/10, 2016 at 20:51 Comment(2)
you create?? no! you can pass arguments to your program through argv. argc is the number of parameters passed in. argv can hold anything values, paths...Mcgehee
@Raindrop7, sometimes you have to create argc and argv inside of a programm. For example if you want to use boost unit test, you will eventually call main. And on android (if you want to run tests on device) you have to call it yourself and you have to form arguments for it.Genius
G
26

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.

Genius answered 5/10, 2016 at 20:57 Comment(7)
implicit conversion from const char * to char * again.Carrillo
I've made conversion explicit and added notice about UB.Genius
For c++11 you can use lvalue reference and &arg[0] without any cast. Anyway I would prefer const_cast<> rather than C-style cast.Carrillo
you have a typo in for (const auto& arg : arguemnts) should be argumentsCrosspollination
Thank you, Ivan. I've fixed the typo.Genius
Ensure that argv doesn't outlive arguments or you will have a use-after-free bug.Laurielaurier
Instead of const-casting you can simply use the non-const version of std::string::data() since C++17Albinus
C
6

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 **)

Controller answered 5/10, 2016 at 20:54 Comment(6)
Conversion from const char * to char * is illegal in c++Carrillo
segfault! no allocation for argvMcgehee
@Carrillo No, it's not. The conversion, if made explicit by a cast, is valid in all versions of C++. Until C++11, the conversion could also be performed implicitly, but only for string literals (which this answer has). Only attempts to modify the pointed-to string are invalid.Stammer
@Mcgehee argv is an array of pointers. Array is on stack, no allocation needed. Pointers are pointers to constants located in data section. No allocation needed either.Genius
@AlexeyGuseynov yes you can pass arguments to another functions even main for example in winmain returns a call to main passing to it argc and argv.Mcgehee
"Attempting to modify a string literal results in undefined behavior: they may be stored in read-only storage (such as .rodata) or combined with other string literals" en.cppreference.com/w/cpp/language/string_literalMurphy

© 2022 - 2024 — McMap. All rights reserved.