Интересные наблюдения argc, argv и его использования - PullRequest
3 голосов
/ 06 февраля 2012

Итак, я работаю над утилитой командной строки на основе Linux, которая должна принимать несколько флагов, и я заметил интересное поведение. Я буду публиковать тестовый код, который я использовал за пределами основной утилиты. Я использовал этот код, поэтому мне не нужно было изменять реальную утилиту, пока у меня не было рабочего кода, который я мог просто вставить. Итак, вот код, с которым я возился:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
    while(--argc && (*++argv)[0] == '-') 
        putchar('*');

    printf("\n%s\n", argv[0]);
 }   

Пожалуйста, игнорируйте тот факт, что все, что делает эта программа, это печатать звездочку и печатать собственное имя при вызове с одним аргументом -b. Печать звездочки должна была просто показать, что цикл прошел один раз. Итак, я запускаю это в терминале как «./test -n», и я ожидал, что результат будет:

*. / Тест

К моему большому удивлению, результат был:

* - б

У меня есть рабочая теория о том, что утверждение (*++argv)[0] делает, но я все еще немного смутен на этом. Я предполагаю, что он пересекает массив указателей, просматривая первый символ в каждой указанной строке, (*++argv)[0] теперь разыменовывает *argv[0] или нулевой элемент первой строки аргумента.

Итак, в основном у меня есть три вопроса:

  1. Что именно делает это утверждение?
  2. Почему я не могу вернуться к argv [0] или argv [0] [0], что бы я ни пытался?
  3. Сохраняет ли значение по адресу, указанному argv [0], в другом символе *, это единственный способ, которым я смог получить доступ к этому значению в этот момент, нормальный способ обойти это?

В данный момент я действительно смущен этим и перепробовал все, что мог придумать, чтобы решить это. В какой-то момент у меня был цикл, который печатал бы алфавит, я не знаю, к какой части памяти обращалась программа. Наиболее интересной перестановкой было извлечение переменных sshid откуда-то.

Заранее всем спасибо за помощь.

1 Ответ

6 голосов
/ 06 февраля 2012

++argv изменяет argv, указывая на следующий аргумент.

Попробуйте что-то вроде

int i = 0;
while(--argc && argv[++i][0] == '-')

, которая поддерживает отдельный индекс вместо перезаписи argv.

Или

char** argp = argv;
while(--argc && (*++argp)[0] == '-')

, который работает так же, как и оригинал, за исключением того, что вместо оригинала изменяется копия argv.

...