LINUX.ORG.RU

Argv в main()

 


0

2

Хочу запустить из своего си кода другую программу с помощью execve() и передать ей часть тех аргументов, что передали моему коду. В документации по execve() сказано, что массив argv должен завершаться NULL. На практике argv[argc] действительно NULL.

Допустим, я хочу передать все аргументы, начиная с третьего. Руки чешутся написать что-то вроде такого:

char** nargv = &argv[2];
execve( ..., nargv, ... );

Насколько такое корректно и могу ли я полагаться на тот NULL-терминатор, который должен быть в конце массива argv? Может ли быть ситуация, что его там попросту не будет?


По идеи, можешь:

#include <stdio.h>

int main(int argc, char **argv) {
    for (int i = 0; argv[i] != NULL; i++) {                                                                                    
        printf("arg #%d is: %s\n", i, argv[i]);
    }
}
$ cc tmp.c && ./a.out test1 test2
arg #0 is: ./a.out
arg #1 is: test1
arg #2 is: test2

Но я бы лучше ориентировался на условие i < argc.

iron ★★★★★
()
Ответ на: комментарий от max_lapshin

А их не нужно менять. Там передаются аргументы сначала для моего кода, а следом аргументы для запускаемой программы. Как мне кажется, идеальный вариант - это передать указатель на тот аргумент, с которого начинаются аргументы для запускаемой моим кодом программы. Весь вопрос был лишь в NULL-терминаторе.

u5er
() автор топика
Ответ на: комментарий от Lrrr

т.ч. NULL в конце гарантируется стандартом C.

Да боже мой, какой нафиг стандарт? У exec* нет никакого argc, потому NULL в последнем argv - это требование логики, а не стандарта.

vodz ★★★★★
()
Ответ на: комментарий от u5er

что передаётся в exec*.

В exec* обычно надо передавать свой сформированный argv, ибо после мало-мальски сложной разборки входных аргументов у вас и argv не тот, а уж argc соврешенно бесполезен, так как после getopt() уже надо пользоваться optind.

vodz ★★★★★
()
Ответ на: комментарий от vodz

после мало-мальски сложной разборки входных аргументов у вас и argv не тот

Можно по подробнее с этого момента? Как понять «не тот»?

Есть список аргументов, которые передаются программе при запуске. Все они кладутся в массив argv в том порядке, в котором они переданы программе. В моём случае первыми идут аргументы, которые предназначены моей программе. Затем следует некий аргумент-разделитель, после которого идут уже аргументы для вызываемой программы. Я просто обрабатываю аргументы до тех пор, пока не встретится разделитель и остальные передаю в вызываемою мной программу.

До этого я создавал статический массив и копировал в него аргументы. Такой способ мне не очень нравился, т.к. заранее не известно количество аргументов, которое передаст пользователь. Теперь я просто передаю указатель на то место, с которого начинаются аргументы для запускаемой программы.

u5er
() автор топика

Почему нельзя для таких целей использовать питон или баш? Если твоя программа только дергает другие бинари чтобы распарсить их вывод, то использование си - оверхед. В таких случаях пользователю уже срать что какое-то действие вместо 1мс выполнится за 10-20

anonymous
()
Ответ на: комментарий от u5er

Можно по подробнее с этого момента? Как понять «не тот»?

Имелось в виду, что getopt переставит в argv в начало опции, а потом аргументы, то есть для prg f1 -o1 f2 вы получите prg -o1 f1 f2

vodz ★★★★★
()