4

I want to pass a vector in as the second argument to execvp. Is it possible?

neuromancer
  • 53,769
  • 78
  • 166
  • 223

3 Answers3

8

Yes, it can be done pretty cleanly by taking advantage of the internal array that vectors use.

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

#include <vector>

using namespace std;

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

  // do a push_back for the command, then each of the arguments
  commandVector.push_back("echo");
  commandVector.push_back("testing");
  commandVector.push_back("1");
  commandVector.push_back("2");
  commandVector.push_back("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[0];

  int status = execvp(command[0], command);
  return 0;
}
Community
  • 1
  • 1
Dillon Kearns
  • 3,675
  • 2
  • 19
  • 9
  • Since C++11 you can also use the std::vector::data() to get the internal array. – hgiesel Mar 18 '16 at 16:16
  • Any suggestions on handling `deprecated conversion from string constant to ‘std::vector::value_type {aka char*}’ [-Wwrite-strings]` warnings for pushing string constants onto `commandVector`? – mpr Aug 31 '17 at 14:34
  • Yeah this is one of those cases in C++ where you have to use a const_cast or really complicate your code (copy all those values into char* variables, not really worth it) – ericcurtin Dec 08 '17 at 12:32
3

Yes, it can be done pretty cleanly by taking advantage of the internal array that vectors use.

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

#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);

  int status = execvp(command[0], &command[0]);
  return 0;
}

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.

ericcurtin
  • 1,499
  • 17
  • 20
2

Not directly; you'd need to represent the vector as a NULL-terminated array of string pointers somehow. If it's a vector of strings, that is straightforward to do; if it's some other kind of data you would have to figure how to encode it as strings.

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234