Printing argv and environ with pointers

117 Views Asked by At

For an exercise we need to print the elements in argv and environ (by looping through the other one). I can get it to print everything but for some reason the first and second pointer element are the same, which doesn't happen when using array indices. e.g.:

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

prints (abbreviated):

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

trying to do the same with a pointer:

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
}   

prints the following (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

The exact same things happens when I print argv by looping through environ, the first and second element print the same thing. I wanted to just loop from size_t = 1 but then it it won't print anything when no additional command line arguments are provided.. Why does this happen and not when using [idx]? I'm sure it's some pointer issue but pointers have always confused me so any help would be appreciated.

2

There are 2 best solutions below

1
On BEST ANSWER

The problem is the location of your line:

ptr = *(environ + idx); 

As it stands, when the value idx is added, it takes the value of the current loop (before idx is incremented). So, after printing out the value on the first run through the for loop, the value of idx added to environ will be ZERO!

If you move that line of code to the beginning of your for loop, it will work!

0
On

Within the loop

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
}

The expression

ptr = *(environ + idx);

gives the same value of the pointer as the expression before the loop

char *ptr = *environ;

in the first iteration of the loop. That is ptr is not changed in the first iteration. *(environ + 0) is the same as *environ when idx is equal to 0.

You could rewrite the loop like

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