Как передать вектор в execvp

Я хочу передать вектор в качестве второго аргумента execvp. Является ли это возможным?


person neuromancer    schedule 01.05.2011    source источник


Ответы (3)


Не напрямую; вам нужно будет каким-то образом представить вектор как массив строковых указателей с нулевым завершением. Если это вектор строк, это сделать просто; если это какие-то другие данные, вам нужно будет понять, как кодировать их в виде строк.

person Jeremy Friesner    schedule 01.05.2011

Да, это можно сделать довольно аккуратно, воспользовавшись внутренним массивом, который используют векторы.

Это будет работать, поскольку стандарт гарантирует, что его элементы хранятся непрерывно (см. 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;
}
person Dillon Kearns    schedule 17.04.2012
comment
Начиная с С++ 11, вы также можете использовать std::vector::data() для получения внутреннего массива. - person hgiesel; 18.03.2016
comment
Любые предложения по обработке предупреждений deprecated conversion from string constant to ‘std::vector<char*>::value_type {aka char*}’ [-Wwrite-strings] о передаче строковых констант в commandVector? - person mpr; 31.08.2017
comment
Да, это один из тех случаев в C++, когда вы должны использовать const_cast или действительно усложнять свой код (скопируйте все эти значения в переменные char*, на самом деле это того не стоит) - person ericcurtin; 08.12.2017

Да, это можно сделать довольно аккуратно, воспользовавшись внутренним массивом, который используют векторы.

Это будет работать, поскольку стандарт гарантирует, что его элементы хранятся непрерывно (см. 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;
}

Выполните const_cast, чтобы избежать "устаревшего преобразования строковой константы в 'char*'". Строковые литералы реализованы как 'const char*' в C++. const_cast — самая безопасная форма приведения, так как она только удаляет константу и не делает никаких других забавных действий. execvp все равно не будет редактировать значения.

Если вы хотите избежать всех приведений, вы должны усложнить этот код, скопировав все значения в типы 'char*', которые на самом деле того не стоят.

person ericcurtin    schedule 08.12.2017