简体   繁体   中英

Access command line arguments in C++

Is it possible to get the command line arguments without receiving them via int main(int, char**)? I don't want to pass the arguments to multiple methods, so a global function would be perfect. Also, I do not want to store the arguments by myself via global variables. I'm running Windows and Linux.

edit: Example:

int main()
{
   int argc = GetArgumentCount();
   char ** argv = GetArguments();
   return 0;
}

edit: It's possible to use LPTSTR WINAPI GetCommandLine(void); in win32.

https://msdn.microsoft.com/en-us/library/ms683156(v=vs.85).aspx

I'm looking for equivalent functions in Linux.

Is it possible to get the command line arguments without receiving them via int main(int, char**) ?

Yes, with platform-specific functions. But that's not necessary (see below).

I don't want to pass the arguments to multiple methods,

That's understandable. It's an anti-pattern also known as "tramp data".

Also, I do not want to store the arguments by myself via global variables.

Yes, global variables are rarely a good idea.

Here's an alternative approach: store them as a static local container object in some globally available non-member function which returns the container by reference.

Example:

#include <iostream>
#include <string>
#include <vector>

std::vector<std::string>& Arguments()
{
    static std::vector<std::string> arguments;
    return arguments;
}

void f()
{
    // use arguments anywhere else:
    std::cout << Arguments()[0];
}

int main(int argc, char* argv[])
{
    for (int i = 0; i < argc; ++i)
    {
        Arguments().push_back(argv[i]);
    }

    f();
}

Of course, this can be made more sophisticated. For example, you might want to prevent anyone else but main from changing the vector by wrapping the vector in a class and declaring main as a friend , something like this:

#include <iostream>
#include <string>
#include <vector>

class Arguments final
{
public:
    static int Count()
    {
        return arguments.size();
    }

    static std::string Get(int index)
    {
        return arguments[index];
    };

private:
    Arguments() = delete;
    friend int main(int argc, char* argv[]);
    static std::vector<std::string> arguments;
};

std::vector<std::string> Arguments::arguments;

void f()
{
    // use Arguments anywhere else:
    std::cout << Arguments::Get(0);
}

int main(int argc, char* argv[])
{
    for (int i = 0; i < argc; ++i)
    {
        Arguments::arguments.push_back(argv[i]);
    }

    f();
}

Note that special care is needed to avoid bugs at program shutdown, when static objects are destroyed. You must make sure that no destructor of a static object accesses Arguments , or else you risk undefined behaviour.

Is it possible to get the command line arguments without receiving them via int main(int, char**) ?

No (at least, not in portable manner ), however you could put the usual argc , argv into some global variable (or other global data, often after parsing). And that could also be into some static data with other functions in the same translation unit retrieving it. Hence a reasonable (readable and portable) approach would be:

static int myargc;
static char **myargv;
int GetArgumentCount(void) {
  return myargc;
}
char**GetArguments(void) {
  return myargv;
}
int main(int argc, char**argv) {
   myargc= argc;
   myargv= argv;
   /// etc....

Notice that on some systems or some implementations you might access to the command line arguments in some other ways.

dirty Linux specific tricks

For example, on Linux, using proc(5) , you might parse /proc/self/cmdline but it is unreasonable to do that (on your Linux system, try to run od -cx /proc/self/cmdline in your terminal to guess what I mean), so I still recommend using int main(int argc, char**argv) and storing, in some global or static data, the argc and argv , or more probably, do some parsing of program arguments .

So on Linux, you might code your GetArgumentCount and GetArguments functions (by parsing /proc/self/cmdline , see also this ) but it would be foolish to do so without using argc and argv from main (even if it is technically doable). Coding such a crazy GetArgumentCount and GetArguments which parses /proc/self/cmdline is left as an exercise to the masochistic reader.

Perhaps you need that because some static data's constructor -running before main and called before it from crt0 - uses them; but in that case, your program's design is IMHO very wrong . I have no idea if similar dirty tricks are doable in Windows.

If you really think that is a good idea, you can easily make cor command line arguments global:

int argc_ = 0;
char** argv_ = NULL;

int main(int argc, char* argv[]) {
    argc_ = argc;
    argv_ = argv;

    // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM