Интересные наблюдения за argc, argv и их использованием

Итак, я работаю над утилитой командной строки на базе 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», и я ожидал, что результат будет таким:

*./контрольная работа

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

*-b

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

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

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

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

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


person Brandon    schedule 06.02.2012    source источник


Ответы (1)


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

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

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

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

Or

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

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

person Ben Voigt    schedule 06.02.2012
comment
Значит, мои предположения были верны. Это обычное дело? Я не сталкивался с этим раньше. - person Brandon; 06.02.2012
comment
Это просто семантика увеличения указателя массива в C. Он не имеет ничего особенного в передаче аргументов программы. - person Basile Starynkevitch; 06.02.2012
comment
Я бы сказал, что это довольно распространенное использование. Не совсем повсеместно, как for(i=0; i‹SOMEVAL; i++), но определенно часто используется при разборе аргументов или при работе со строками строк в каком-то другом контексте. - person Barton Chittenden; 06.02.2012
comment
Василий, я видел геопт, но в данный момент его использование не в моих силах. Я пытаюсь выучить C и пишу для этого небольшие и средние программы. Это текущее упражнение было более или менее предназначено для изучения некоторых более тонких аспектов захвата аргументов, а также указателей, а также некоторых более сложных аспектов указателей. Я уверен, что вернусь, когда начну пытаться понять концепцию указателей на функции и указателей на структуры. - person Brandon; 06.02.2012