How to pass a vector of strings to execv

execv() accepts only an array of string pointers. There is no way to get it to accept anything else. It is a standard interface, callable from every hosted language, not just C++.

I have tested compiling this:

    std::vector<string> vector;
    const char *programname = "abc";

    const char **argv = new const char* [vector.size()+2];   // extra room for program name and sentinel
    argv [0] = programname;         // by convention, argv[0] is program name
    for (int j = 0;  j < vector.size()+1;  ++j)     // copy args
            argv [j+1] = vector[j] .c_str();

    argv [vector.size()+1] = NULL;  // end of arguments sentinel is NULL

    execv (programname, (char **)argv);

Yes, it can be done pretty cleanly by taking advantage of the internal array that vectors use. Best to not use C++ strings in the vector, and const_cast string literals and string.c_str()'s to char*.

This will work, since the standard guarantees its elements are stored contiguously (see https://stackoverflow.com/a/2923290/383983)

#include <unistd.h>
#include <vector>

using std::vector;

int main() {
  vector<char*> commandVector;

  // do a push_back for the command, then each of the arguments
  commandVector.push_back(const_cast<char*>("echo"));
  commandVector.push_back(const_cast<char*>("testing"));
  commandVector.push_back(const_cast<char*>("1"));
  commandVector.push_back(const_cast<char*>("2"));
  commandVector.push_back(const_cast<char*>("3"));

  // push NULL to the end of the vector (execvp expects NULL as last element)
  commandVector.push_back(NULL);

  // pass the vector's internal array to execvp
  char **command = commandVector.data();

  execvp(command[0], &command[0]);
  return 1;
}

Code adapted from: How to pass a vector to execvp

Do a const_cast to avoid the "deprecated conversion from string constant to 'char*'". String literals are implemented as 'const char*' in C++. const_cast is the safest form of cast here, as it only removes the const and does not do any other funny business. execvp will not edit the values anyway.

If you want to avoid all casts, you have to complicate this code by copying all the values to 'char*' types not really worth it.

Although if the number of arguments you want to pass to execv/execl is known, it's easier to write this in C.


The prototype for execv is:

int execv(const char *path, char *const argv[]);

That means the argument list is an array of pointers to null-terminated c strings.

You have vector<string>. Find out the size of that vector and make an array of pointers to char. Then loop through the vector and for each string in the vector set the corresponding element of the array to point to it.

Tags:

C++

String

Vector