Печать argv и environment с помощью указателей - PullRequest
0 голосов
/ 15 октября 2019

Для упражнения нам нужно напечатать элементы в argv и environment (циклически перебирая остальные). Я могу заставить его печатать все, но по какой-то причине первый и второй элемент указателя одинаковы, чего не происходит при использовании индексов массива. Например:

size_t idx = 0;
while (environ[idx])
{
     cout << idx << " = " << environ[idx] << '\n';
     ++idx;
}

печатает (сокращенно):

0 = XDG_VTNR=7
1 = XDG_SESSION_ID=c4
2 = XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/*********
3 = CLUTTER_IM_MODULE=
4 = DBUS_STARTER_ADDRESS=unix:abstract=/tmp/dbus-qBmfhGvfX0,guid=33afede959ece95fbd4e3c055da5de6c
5 = QT_STYLE_OVERRIDE=gtk
6 = GPG_AGENT_INFO=/home/s2161915/.gnupg/S.gpg-agent:0:1

пытается сделать то же самое с указателем:

char *ptr = *environ;   
for (size_t idx = 0; *(argv + idx); ++idx)
{   
    if (ptr)                            // ptr isn't a nullptr
    {
        cout << idx << ": env: " << ptr << '\n'; 
        // make ptr point to next element in environ
        ptr = *(environ + idx);         
    } else
        break;                          // end of environ
}   

печатает следующее (argc = 7):

0: env: XDG_VTNR=7
1: env: XDG_VTNR=7
2: env: XDG_SESSION_ID=c4
3: env: XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/*********
4: env: CLUTTER_IM_MODULE=
5: env: DBUS_STARTER_ADDRESS=unix:abstract=/tmp/dbus-qBmfhGvfX0,guid=33afede959ece95fbd4e3c055da5de6c
6: env: QT_STYLE_OVERRIDE=gtk

Точно такие же вещи случаются, когда я печатаю argv, перебирая окружение, первый и второй элементы печатают одно и то же. Я хотел просто зациклить с size_t = 1, но тогда он ничего не печатает, если не предоставлены дополнительные аргументы командной строки. Почему это происходит, а не при использовании [idx]? Я уверен, что это некоторая проблема с указателями, но указатели всегда смущали меня, поэтому любая помощь будет принята с благодарностью.

Ответы [ 2 ]

3 голосов
/ 15 октября 2019

Проблема в расположении вашей строки:

ptr = *(environ + idx); 

В текущем состоянии, когда добавляется значение idx, оно принимает значение токовой петли (до увеличения idx),Таким образом, после вывода значения при первом запуске через цикл for значение idx, добавленное к environ, будет НУЛЕВЫМ!

Если переместить эту строку кода в начало вашего for цикла, оно будет работать!

2 голосов
/ 15 октября 2019

Внутри цикла

char *ptr = *environ;   
for (size_t idx = 0; *(argv + idx); ++idx)
{   
    if (ptr)                            // ptr isn't a nullptr
    {
        cout << idx << ": env: " << ptr << '\n'; 
        // make ptr point to next element in environ
        ptr = *(environ + idx);         
    } else
        break;                          // end of environ
}

Выражение

ptr = *(environ + idx);

дает то же значение указателя, что и выражение перед циклом

char *ptr = *environ;

вПервая итерация цикла. То есть ptr не изменяется в первой итерации. *(environ + 0) совпадает с *environ, когда idx равно 0.

Вы можете переписать цикл как

char *ptr;   
for (size_t idx = 0; ( ptr = *(argv + idx) ) != nullptr; ++idx)
{   
    cout << idx << ": env: " << ptr << '\n'; 
}  
...