Указатель на * argv []

Это мой main.c

......
int main(int argc, char **argv)
{
    init_arg(&argc, &argv);
    ......
}

Это мой init_arg.c

......
void init_arg(int *argc, char ***argv)
{
    printf("%s\n", *argv[1]);
    ......
}

Я компиляю его без ошибок и предупреждений.

Я запускаю его:

./a.out include

Он получает Ошибка сегментации

Когда я его отлаживаю, я нашел шаг printf("%s\n", *argv[1]);

Неправильно, он показывает:

print *argv[1]

Cannot access memory at address 0x300402bfd

Я хочу знать, как печатать argv[1] в init_arg().

Ответы

Ответ 1

Вам нужно добавить пару круглых скобок (* argv), чтобы изменить порядок оценки. То, как вы в настоящее время его используете, сначала оценивается [1], что дает недопустимый указатель, который затем разыменовывается, вызывая поведение undefined.

printf("%s\n", (*argv)[1]);

Ответ 2

Аргв уже является указателем. Просто передайте его вот так:

init_arg(&argc, argv);

И init_arg должен выглядеть так:

void init_arg(int *argc, char **argv) {
    printf("%s\n", argv[1]);
}

Ответ 3

Я предполагаю, что причина прохождения &argc и &argv в первую очередь заключается в том, что вы можете обновлять их внутри init_arg. Вот как я предпочитаю писать такие функции, в общем случае:

/*
 * init_arg: do something useful with argc and argv, and update argc and argv
 * before returning so that the caller can do something else useful that's
 * not shared with all the other callers of init_arg().
 * (this comment of course needs updating to describe the useful things)
 */
void init_arg(int *argc0, char ***argv0) {
    int argc = *argc0;
    char **argv = *argv0;
    ... all the operative code goes here, and then ...
    *argc0 = argc;
    *argv0 = argv;
}

Конечно, это означает, что вы не должны делать ранние return внутри init_arg, поэтому есть некоторые компромиссы, но гораздо легче работать с теми же обычными старыми argc и argv внутри init_arg.