Is it possible to change argv or do I need to create an adjusted copy of it?

25,722

Solution 1

Once argv has been passed into the main method, you can treat it like any other C array - change it in place as you like, just be aware of what you're doing with it. The contents of the array don't have an effect on the return code or execution of the program other than what you explicitly do with it in code. I can't think of any reason it wouldn't "be advisable" to treat it specially.

Of course, you still need to take care about accidentally accessing memory beyond the bounds of argv. The flip side of it being accessible like a normal C array is that it's also prone to access errors just like any other normal C array. (Thanks to all who pointed this out in comments and other responses!)

Solution 2

The C99 standard says this about modifying argv (and argc):

The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.

Solution 3

The latest draft of the C standard (N1256) states that there are two allowed forms of the main function:

int main (void);
int main (int argc, char* argv[]);

but the crux is the clause "or in some other implementation-defined manner". This seems to me to be a loophole in the standard large enough to drive a semi-trailer through.

Some people specifically use "const char *" for the argv to disallow changes to the arguments. If your main function is defined that way, you are not permitted to change the characters that argv[] points to, as evidenced by the following program:

pax> cat qq.c
#include <stdio.h>
int main (int c, const char *v[]) {
    *v[1] = 'X';
    printf ("[%s]\n", v[1]);
    return 0;
}

pax> gcc -o qq qq.c
qq.c: In function `main':
qq.c:3: error: assignment of read-only location

However, if you remove the "const", it works fine:

pax> cat qq2.c
#include <stdio.h>
int main (int c, char *v[]) {
    *v[1] = 'X';
    printf ("[%s]\n", v[1]);
    return 0;
}

pax> gcc -o qq2 qq2.c ; ./qq2
[Xello]

I think this is also the case for C++. The current draft states:

All implementations shall allow both of the following definitions of main:
    int main();
    int main(int argc, char* argv[]);

but it doesn't specifically disallow other variants so you could presumably accept a "const" version in C++ as well (and, in fact, g++ does).

The only thing you need to be careful of is trying to increase the size of any of the elements. The standards do not mandate how they're stored so extending one argument may (probably will) affect others, or some other unrelated data.

Solution 4

Empirically, functions such as GNU getopt() permute the argument list without causing problems. As @Tim says, as long as you play sensibly, you can manipulate the array of pointers, and even individual strings. Just don't overrun any of the implicit array boundaries.

Solution 5

The operating system push the argv and argc into the applicaton stack before executing it, and you can treat them like any other stack variables.

Share:
25,722
ojblass
Author by

ojblass

Only a little special.

Updated on May 18, 2020

Comments

  • ojblass
    ojblass about 4 years

    My application has potentially a huge number of arguments passed in and I want to avoid the memory of hit duplicating the arguments into a filtered list. I would like to filter them in place but I am pretty sure that messing with argv array itself, or any of the data it points to, is probably not advisable. Any suggestions?