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 ★★★★★
()