Is it OK to modify argv ???

Discussion in 'C Programming' started by Charles Sullivan, Sep 13, 2003.

  1. I'm working on a program which has a "tree" of command line arguments,
    i.e.,
    myprogram level1 [ level2 [ level3 ...]]]
    such that there can be more than one level2 argument for each level1
    argument and more than one level3 argument for each level2 argument, etc.

    Suppose I code it similar to this fragment:

    int main( int argc, char *argv[] )
    {
    ...
    if ( strcmp(argv[1], "blivet") == 0 )
    return do_blivet( --argc, ++argv );
    else if ( ...
    ...
    }

    int do_blivet( int argc, char *argv[] ) {
    ...
    if ( strcmp(argv[1], "whosis") == 0 )
    return do_whosis( --argc, ++argv );
    else if ( ...
    ...
    }

    It turns out to be somewhat more convenient in practise to increment
    argv as above than to pass the argument (argv + 1).

    My question: Is it correct C code to increment argv as above?
    I'm wondering whether doing this might prevent memory
    allocated for array *argv[] from being freed upon program exit,
    under some operating systems.

    Thanks for your advice.

    Regards,
    Charles Sullivan
    Charles Sullivan, Sep 13, 2003
    #1
    1. Advertising

  2. Charles Sullivan

    Mike Wahler Guest

    Charles Sullivan <> wrote in message
    news:p...
    > I'm working on a program which has a "tree" of command line arguments,
    > i.e.,
    > myprogram level1 [ level2 [ level3 ...]]]
    > such that there can be more than one level2 argument for each level1
    > argument and more than one level3 argument for each level2 argument, etc.
    >
    > Suppose I code it similar to this fragment:
    >
    > int main( int argc, char *argv[] )
    > {
    > ...
    > if ( strcmp(argv[1], "blivet") == 0 )
    > return do_blivet( --argc, ++argv );
    > else if ( ...
    > ...
    > }
    >
    > int do_blivet( int argc, char *argv[] ) {
    > ...
    > if ( strcmp(argv[1], "whosis") == 0 )
    > return do_whosis( --argc, ++argv );
    > else if ( ...
    > ...
    > }
    >
    > It turns out to be somewhat more convenient in practise to increment
    > argv as above than to pass the argument (argv + 1).
    >
    > My question: Is it correct C code to increment argv as above?
    > I'm wondering whether doing this might prevent memory
    > allocated for array *argv[] from being freed upon program exit,
    > under some operating systems.
    >
    > Thanks for your advice.


    Remember that C arguments are passed 'by value'.
    So any changes you make to a function's parameters
    will not be reflected by the caller. 'main()' is
    no different from any other function in this respect.

    -Mike
    Mike Wahler, Sep 13, 2003
    #2
    1. Advertising

  3. Charles Sullivan wrote:

    > I'm working on a program which has a "tree" of command line arguments,


    int main(int argc, char **argv)
    {
    it's okay to modify argv, because it's just a copy of a pointer.

    argv++; /* no problem here */

    it's okay to modify argv[n], provided such a character exists. Thus:

    if(strlen(argv[1]) > strlen("hello")
    {
    strcpy(argv[1], "hello"); /* no problem here */
    }

    it's NOT okay to modify the pointer argv:

    argv = "new pointer value"; /* BUG! */

    >
    > It turns out to be somewhat more convenient in practise to increment
    > argv as above than to pass the argument (argv + 1).
    >
    > My question: Is it correct C code to increment argv as above?


    Yes, that's fine.

    > I'm wondering whether doing this might prevent memory
    > allocated for array *argv[] from being freed upon program exit,
    > under some operating systems.


    As long as you stick to the rules I outlined above (and all the other rules,
    and some more that I haven't thought of yet), you'll be fine.

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
    Richard Heathfield, Sep 13, 2003
    #3
  4. Charles Sullivan <> wrote:

    <SNIP>
    >
    >int do_blivet( int argc, char *argv[] ) {
    > ...
    > if ( strcmp(argv[1], "whosis") == 0 )
    > return do_whosis( --argc, ++argv );
    > else if ( ...
    > ...
    >}
    >
    >It turns out to be somewhat more convenient in practise to increment
    >argv as above than to pass the argument (argv + 1).
    >
    >My question: Is it correct C code to increment argv as above?
    >I'm wondering whether doing this might prevent memory
    >allocated for array *argv[] from being freed upon program exit,
    >under some operating systems.
    >

    argc and argv have function scope, IOW they are local to main();
    thus, you may arbitrarily change their values without doing harm
    to anything that happens to take place outside of main().

    Regards,

    Irrwahn
    --
    do not write: void main(...)
    do not use gets()
    do not cast the return value of malloc()
    do not fflush( stdin )
    read the c.l.c-faq: http://www.eskimo.com/~scs/C-faq/top.html
    Irrwahn Grausewitz, Sep 13, 2003
    #4
  5. Charles Sullivan

    Kevin Easton Guest

    Charles Sullivan <> wrote:
    > I'm working on a program which has a "tree" of command line arguments,
    > i.e.,
    > myprogram level1 [ level2 [ level3 ...]]]
    > such that there can be more than one level2 argument for each level1
    > argument and more than one level3 argument for each level2 argument, etc.
    >
    > Suppose I code it similar to this fragment:
    >
    > int main( int argc, char *argv[] )
    > {
    > ...
    > if ( strcmp(argv[1], "blivet") == 0 )
    > return do_blivet( --argc, ++argv );
    > else if ( ...
    > ...
    > }
    >
    > int do_blivet( int argc, char *argv[] ) {
    > ...
    > if ( strcmp(argv[1], "whosis") == 0 )
    > return do_whosis( --argc, ++argv );
    > else if ( ...
    > ...
    > }
    >
    > It turns out to be somewhat more convenient in practise to increment
    > argv as above than to pass the argument (argv + 1).
    >
    > My question: Is it correct C code to increment argv as above?


    Yes, it's just a regular function paramater.

    - Kevin.
    Kevin Easton, Sep 13, 2003
    #5
  6. Charles Sullivan

    Malcolm Guest

    "Charles Sullivan" <> wrote in message
    > It turns out to be somewhat more convenient in practise to increment
    > argv as above than to pass the argument (argv + 1).
    >
    > My question: Is it correct C code to increment argv as above?
    >

    It is OK. It may not be a good idea. There is a school of thought that
    function parameters shouldn't be modified at all by the callee. In a
    mathematical function this makes sense, since in mathematical convention the
    symbols have constant values.
    In the case of argv and argc , a maintaining programmer wouldn't expect
    these to be modified, and might wonder why argv[0] no longer pointed to the
    program name.
    On the other hand, if the code does look a lot clearer with the
    modification, then it is quite hard to argue that you shouldn't use it.
    Malcolm, Sep 13, 2003
    #6
  7. >> I'm working on a program which has a "tree" of command line arguments,
    >
    >int main(int argc, char **argv)
    >{
    > it's okay to modify argv[n], provided such a character exists. Thus:
    >
    > if(strlen(argv[1]) > strlen("hello")
    > {
    > strcpy(argv[1], "hello"); /* no problem here */
    > }
    >


    > it's NOT okay to modify the pointer argv:
    >
    > argv = "new pointer value"; /* BUG! */


    Why that? argv[n] is just a copy too, that is, argv and argv[*] are within the
    stack, and even argv[*][*] is.

    --
    - Jan Engelhardt
    Jan Engelhardt, Sep 13, 2003
    #7
  8. Jan Engelhardt <> wrote:

    >>> I'm working on a program which has a "tree" of command line arguments,

    >>
    >>int main(int argc, char **argv)
    >>{
    >> it's okay to modify argv[n], provided such a character exists. Thus:
    >>
    >> if(strlen(argv[1]) > strlen("hello")
    >> {
    >> strcpy(argv[1], "hello"); /* no problem here */
    >> }
    >>

    >
    >> it's NOT okay to modify the pointer argv:
    >>
    >> argv = "new pointer value"; /* BUG! */

    >
    >Why that? argv[n] is just a copy too, that is, argv and argv[*] are within the
    >stack, and even argv[*][*] is.


    Errm..., could you please elaborate on this?

    Hint: Where does argv point to?

    BTW: There's nothing like a stack from the C POV.

    Regards

    Irrwahn
    --
    do not write: void main(...)
    do not use gets()
    do not cast the return value of malloc()
    do not fflush( stdin )
    read the c.l.c-faq: http://www.eskimo.com/~scs/C-faq/top.html
    Irrwahn Grausewitz, Sep 13, 2003
    #8
  9. Jan Engelhardt wrote:

    >>> I'm working on a program which has a "tree" of command line arguments,

    >>
    >>int main(int argc, char **argv)
    >>{
    >> it's okay to modify argv[n], provided such a character exists. Thus:
    >>
    >> if(strlen(argv[1]) > strlen("hello")
    >> {
    >> strcpy(argv[1], "hello"); /* no problem here */
    >> }
    >>

    >
    >> it's NOT okay to modify the pointer argv:
    >>
    >> argv = "new pointer value"; /* BUG! */

    >
    > Why that? argv[n] is just a copy too,


    Wrong. Consider the following code:

    #include <stdlib.h>
    int foo(char **v)
    {
    char *p = "Hello";
    v[0] = p;
    }
    int main(void)
    {
    char *v[1] = {0};
    v[0] = malloc(10);
    if(v[0] != NULL)
    {
    foo(v);
    free(v[0]); /* bang! */
    }
    return 0;
    }

    > that is, argv and argv[*] are within
    > the stack, and even argv[*][*] is.


    The Standard says:

    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.

    Since nothing is said about the pointers themselves, we must assume they are
    non-modifiable.

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
    Richard Heathfield, Sep 13, 2003
    #9
  10. Charles Sullivan

    Matt Gregory Guest

    Richard Heathfield wrote:

    > The Standard says:
    >
    > 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.
    >
    > Since nothing is said about the pointers themselves, we must assume they are
    > non-modifiable.


    Is it non-portable to swap them, though, like getopt() does?

    char *temp = argv[2];
    argv[2] = argv[1];
    argv[1] = temp;

    What's the story on that?
    Matt Gregory, Sep 14, 2003
    #10
  11. Matt Gregory wrote:

    > Richard Heathfield wrote:
    >
    >> The Standard says:
    >>
    >> 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.
    >>
    >> Since nothing is said about the pointers themselves, we must assume they
    >> are non-modifiable.

    >
    > Is it non-portable to swap them, though, like getopt() does?
    >
    > char *temp = argv[2];
    > argv[2] = argv[1];
    > argv[1] = temp;
    >
    > What's the story on that?


    Undefined behaviour, IMHO, for the reason stated above. Of course, I'm ready
    to be corrected by anyone with appropriate C&V.

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
    Richard Heathfield, Sep 14, 2003
    #11
  12. Re: Is it OK to modify argv ??? - Thanks !

    Thanks folks. You've answered my question and also helped clarify my
    thinking.

    Much appreciated!

    Regards,
    Charles Sullivan
    Charles Sullivan, Sep 14, 2003
    #12
  13. On Sat, 13 Sep 2003 19:01:24 UTC, Irrwahn Grausewitz
    <> wrote:

    > Jan Engelhardt <> wrote:
    >
    > >>> I'm working on a program which has a "tree" of command line arguments,
    > >>
    > >>int main(int argc, char **argv)
    > >>{
    > >> it's okay to modify argv[n], provided such a character exists. Thus:
    > >>
    > >> if(strlen(argv[1]) > strlen("hello")
    > >> {
    > >> strcpy(argv[1], "hello"); /* no problem here */
    > >> }
    > >>

    > >
    > >> it's NOT okay to modify the pointer argv:
    > >>
    > >> argv = "new pointer value"; /* BUG! */

    > >
    > >Why that? argv[n] is just a copy too, that is, argv and argv[*] are within the
    > >stack, and even argv[*][*] is.

    >
    > Errm..., could you please elaborate on this?
    >
    > Hint: Where does argv point to?


    argv points to an array of pointers. It is possible to change one or
    all of them.
    argv[] points to an zero termitated array of chars. It is possible to
    change any char in that array. You may even store any other string
    that is equal in size or shorter than the initial one there. Storing a
    string that is longer results in undefined behavior.

    --
    Tschau/Bye
    Herbert

    eComStation 1.1 Deutsch Beta ist verügbar
    The Real OS/2 Guy, Sep 14, 2003
    #13
  14. On Sat, 13 Sep 2003 23:12:44 UTC, Matt Gregory
    <> wrote:

    > Richard Heathfield wrote:
    >
    > > The Standard says:
    > >
    > > 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.
    > >
    > > Since nothing is said about the pointers themselves, we must assume they are
    > > non-modifiable.


    What is argv? It is a pointer to an array of pointers. So any pointer
    argv points to is changeable.
    Any string a pointer in the array of pointers is changeable too.

    > Is it non-portable to swap them, though, like getopt() does?
    >
    > char *temp = argv[2];
    > argv[2] = argv[1];
    > argv[1] = temp;
    >
    > What's the story on that?
    >

    It is portable. The only you can't do is to insert more pointers as
    argc says it has at startup.

    At startup argc contains the number of pointers argv points to.
    Changing the sequence in the array is ok. Changing any pointer in the
    array to whatever is ok too. Adding more pointers as the initial value
    has is NOT ok.

    Changing an array arv[] poits to is ok. You may shorten this array as
    kile. Extending it results in undefined behavior.

    argv is in memory the application has unlimited access to (else the
    CRT would fail to build it).

    argv is nothing than each other pointer to an array of pointers that
    points to strings.

    --
    Tschau/Bye
    Herbert

    eComStation 1.1 Deutsch Beta ist verügbar
    The Real OS/2 Guy, Sep 14, 2003
    #14
  15. "The Real OS/2 Guy" <> wrote:

    >On Sat, 13 Sep 2003 19:01:24 UTC, Irrwahn Grausewitz
    ><> wrote:
    >
    >> Jan Engelhardt <> wrote:
    >> >
    >> > Richard Heathfield wrote:
    >> >>
    >> >> it's NOT okay to modify the pointer argv:
    >> >>
    >> >> argv = "new pointer value"; /* BUG! */
    >> >
    >> >Why that? argv[n] is just a copy too, that is, argv and argv[*] are within the
    >> >stack, and even argv[*][*] is.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    >>
    >> Errm..., could you please elaborate on this?
    >>
    >> Hint: Where does argv point to?

    >
    >argv points to an array of pointers. It is possible to change one or
    >all of them.
    >argv[] points to an zero termitated array of chars. It is possible to
    >change any char in that array. You may even store any other string
    >that is equal in size or shorter than the initial one there. Storing a
    >string that is longer results in undefined behavior.


    This discussion was not about changing the /characters/ pointed to, it
    was about changing the /pointer/ values. And JE's claim that argv[n]
    is a local copy of a pointer (just like argv, which undoubtely is), is
    plain wrong.

    Irrwahn
    --
    Proofread carefully to see if you any words out.
    Irrwahn Grausewitz, Sep 14, 2003
    #15
  16. "The Real OS/2 Guy" <> wrote:

    >On Sat, 13 Sep 2003 23:12:44 UTC, Matt Gregory
    ><> wrote:
    >
    >> Richard Heathfield wrote:
    >>
    >> > The Standard says:
    >> >
    >> > 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.
    >> >
    >> > Since nothing is said about the pointers themselves, we must assume they are
    >> > non-modifiable.

    >
    >What is argv? It is a pointer to an array of pointers. So any pointer
    >argv points to is changeable.
    >Any string a pointer in the array of pointers is changeable too.
    >
    >> Is it non-portable to swap them, though, like getopt() does?
    >>
    >> char *temp = argv[2];
    >> argv[2] = argv[1];
    >> argv[1] = temp;
    >>
    >> What's the story on that?
    >>

    >It is portable. The only you can't do is to insert more pointers as
    >argc says it has at startup.
    >
    >At startup argc contains the number of pointers argv points to.
    >Changing the sequence in the array is ok. Changing any pointer in the
    >array to whatever is ok too.


    To whatever? So you consider the last line of the following code that
    Richard posted upthread to be correct (comment delimiters deliberately
    added)?

    RH> int main(int argc, char **argv)
    RH> {
    RH> /* it's okay to modify argv, because it's just a copy of a
    RH> pointer.*/
    RH>
    RH> argv++; /* no problem here */
    RH>
    RH> /* it's okay to modify argv[n], provided such a character
    RH> exists. Thus:*/
    RH>
    RH> if(strlen(argv[1]) > strlen("hello")
    RH> {
    RH> strcpy(argv[1], "hello"); /* no problem here */
    RH> }
    RH>
    RH> /* it's NOT okay to modify the pointer argv: */
    RH>
    RH> argv = "new pointer value"; /* BUG! */
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    This is the interesting line.

    Irrwahn
    --
    Close your eyes and press escape three times.
    Irrwahn Grausewitz, Sep 14, 2003
    #16
  17. The Real OS/2 Guy wrote:

    > On Sat, 13 Sep 2003 23:12:44 UTC, Matt Gregory
    > <> wrote:
    >
    >> char *temp = argv[2];
    >> argv[2] = argv[1];
    >> argv[1] = temp;
    >>
    >> What's the story on that?
    >>

    > It is portable.


    I disagree. The standard gives explicit permission to modify argv itself and
    the strings pointed to by argv[0] through argv[argc - 1], but it doesn't
    give permission to modify argv[0] through argv[argc - 1] themselves.

    If you can provide C&V to back up your point of view, please do so.

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
    Richard Heathfield, Sep 14, 2003
    #17
  18. On Sun, 14 Sep 2003 14:57:11 UTC, Irrwahn Grausewitz
    <> wrote:

    >
    > To whatever? So you consider the last line of the following code that
    > Richard posted upthread to be correct (comment delimiters deliberately
    > added)?
    > RH> /* it's NOT okay to modify the pointer argv: */
    > RH>
    > RH> argv = "new pointer value"; /* BUG! */
    > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    > This is the interesting line.

    Yes - so long i is < argc and he has either saved the string argv
    points to before or has really no interest on the parameter he's
    loosing now.

    --
    Tschau/Bye
    Herbert

    eComStation 1.1 Deutsch Beta ist verügbar
    The Real OS/2 Guy, Sep 14, 2003
    #18
  19. "The Real OS/2 Guy" <> wrote:

    >On Sun, 14 Sep 2003 14:57:11 UTC, Irrwahn Grausewitz
    ><> wrote:
    >
    >>
    >> To whatever? So you consider the last line of the following code that
    >> Richard posted upthread to be correct (comment delimiters deliberately
    >> added)?
    >> RH> /* it's NOT okay to modify the pointer argv: */
    >> RH>
    >> RH> argv = "new pointer value"; /* BUG! */
    >> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    >> This is the interesting line.

    >Yes - so long i is < argc and he has either saved the string argv
    >points to before or has really no interest on the parameter he's
    >loosing now.


    Which part of the standard makes you think so? Chapter and verse,
    please.
    --
    Close your eyes and press escape three times.
    Irrwahn Grausewitz, Sep 14, 2003
    #19
  20. On Sun, 14 Sep 2003, The Real OS/2 Guy wrote:
    >
    > On Sun, 14 Sep 2003 14:57:11 UTC, Irrwahn Grausewitz wrote:
    > >
    > > To whatever? So you consider the last line of the following code that
    > > Richard posted upthread to be correct (comment delimiters deliberately
    > > added)?
    > >
    > > RH> /* it's NOT okay to modify the pointer argv: */
    > > RH>
    > > RH> argv = "new pointer value"; /* BUG! */
    > > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    > > This is the interesting line.

    >
    > Yes - so long i is < argc and he has either saved the string argv
    > points to before or has really no interest on the parameter he's
    > loosing now.



    % cat last-message

    > > To whatever? So you consider the last line of the following code that
    > > Richard posted upthread to be correct (comment delimiters deliberately
    > > added)?


    % /imaginary/bin/remove-rhetoric < last-message

    > > So you're wrong, obviously. Consult the Standard. argv is
    > > not modifiable. Period. End of discussion.


    %


    -Arthur
    Arthur J. O'Dwyer, Sep 15, 2003
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bret

    char **argv vs. char* argv[]

    Bret, Aug 31, 2003, in forum: C Programming
    Replies:
    21
    Views:
    4,581
    Richard Heathfield
    Sep 3, 2003
  2. David
    Replies:
    10
    Views:
    5,950
    Richard Heathfield
    Sep 15, 2003
  3. Hal Styli
    Replies:
    14
    Views:
    1,629
    Old Wolf
    Jan 20, 2004
  4. =?ISO-8859-1?Q?Thomas_N=FCcker?=

    sys.argv[0] - 'module' object has no attribute 'argv'

    =?ISO-8859-1?Q?Thomas_N=FCcker?=, Jun 30, 2003, in forum: Python
    Replies:
    0
    Views:
    901
    =?ISO-8859-1?Q?Thomas_N=FCcker?=
    Jun 30, 2003
  5. jab3

    char **argv & char *argv[]

    jab3, Dec 4, 2004, in forum: C Programming
    Replies:
    5
    Views:
    665
    Chris Torek
    Dec 8, 2004
Loading...

Share This Page