1

After reading Is argv[n] writable?, I'm not completely certain what conclusions to take from the thread.

The C standard, from C89 onwards, states:

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.

In a program, I've been testing the following code:

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

    for (i = 1; i < argc; i++)
    {
        /* Do something */
        argv[i] = NULL; /* argv[i] is no longer needed */
    }

    for (i = 1; i < argc; i++)
    {
        if (argv[i])
            /* Do something else */
    }
}

While this works for me on Linx Mint 17.2 with gcc 4.8.4, setting argv[i] = NULL seems to be both valid and non-standardized behaviour, at least according to the standard. This makes me reluctant to use this code in production.

(I'm basically iterating over argv twice, making sure I skip argv[i] == NULL.)

  1. What kind of evidence, if any, is there to support re-assigning argv[i] in this way? I'm concerned I might cause memory and/or compiler problems, as I can't guarantee how other systems will handle this.

  2. Is there a better method to do what I want to do?

EDIT

I forgot to add that the input args consist of flags and filenames. These can be in any order, so I'm using argv[i] = NULL to help me identify filenames. - and / are valid for filenames and flags.

EDIT 2

The standard talks about argv and the strings pointed to by the argv array. Those can be modified. But what about the pointers themselves. Does the standard explicitly say they can be modified? Or am I misinterpreting the standard?

Community
  • 1
  • 1
Hugh McMaster
  • 319
  • 3
  • 10
  • 6
    I don't understand what exactly the problem is. The Standard says that the `argv` array (and even the pointed strings) should be writable. So you are allowed to change them. Specifically what makes you think that it's "non-standardized behaviour"? – The Paramagnetic Croissant Jul 13 '15 at 11:20
  • I deleted already typed two-line question which is just as same as @TheParamagneticCroissant :-) – Sourav Ghosh Jul 13 '15 at 11:21
  • @TheParamagneticCroissant My understanding is that `argv` can be modified as the 'root' pointer. And modifiying `argv[i][j]` is only modifying a single `char`. Unless I'm interpreting the standard incorrectly, it does not mention the pointers themselves. – Hugh McMaster Jul 13 '15 at 11:29
  • 1
    "*it does not mention the pointers themselves*" this indeed is correct. But also the Standard does not mention that those pointer may not be changed. – alk Jul 13 '15 at 11:34
  • 1
    Re-assigning `argv[i]` seems to be what GLib is doing in `g_option_context_parse()`. [Source code](https://git.gnome.org/browse/glib/tree/glib/goption.c#n2174). (Here the address of `argv` is passed so `*argv` is actually `char **`.) – user12205 Jul 13 '15 at 11:34
  • @alk "non-standardized behaviour" was a poor choice of words. My question is really about what the standard does not say (see Edit 2). – Hugh McMaster Jul 13 '15 at 11:35
  • @alk _But also the Standard does not mention that those pointer may not be changed._ This is my dilemma. Can I expect modifying the pointers to work on different systems/compilers? – Hugh McMaster Jul 13 '15 at 11:46
  • @ace Good find. Thank you. – Hugh McMaster Jul 13 '15 at 11:54
  • 2
    @HughMcMaster "and the strings pointed to by the argv array" can be interpreted as "both the pointer-to-char and the char itself", can it not? I'm sure that the thorough enumeration of the standard wants to express that "these are all permitted". Maybe it's not the best wording, but IMO the intent is quite clear. – The Paramagnetic Croissant Jul 13 '15 at 12:21

4 Answers4

1

I'm not sure what you want to do, but nothing prevents you from using an extra array storing flags that you'd set instead of clearing up argv[i]!

franciscod
  • 992
  • 4
  • 17
0

the strings pointed to by the argv array

I think you are mistaken.

argv is NOT an array of character pointers,

argv is a pointer to a character pointer which is the first element of an array of char-pointers (commonly being referred to as argv array) that contain the arguments, one per string.

So there is no problem modifying any valid argv[i].

alk
  • 69,737
  • 10
  • 105
  • 255
Raman
  • 2,735
  • 1
  • 26
  • 46
  • 1
    Hm... to start a post with "I think you are mistaken" is of little help, and then using fuzzy language (to say the least) does not make a post better. argv is a pointer to a char pointer (the parameter declarations `char *argv[]`and `char **argv` are equivalent), with the implied semantics that the pointee is the first of `argc` elements in a NULL terminated array of pointers. (An "array of character strings", by contrast, would be a two-dimensional char array whose "strings" would be -- hopefully -- `\0` terminated character arrays. That is not what argv points to.) – Peter - Reinstate Monica Jul 13 '15 at 12:23
  • @PeterSchneider All I've done is copied that statement(*argv is a pointer to an array of character strings*) from K&R c 2nd edition pdf. And I don't understand what is the difference? – Raman Jul 13 '15 at 12:28
  • Nice image (seriously), but why not fix the wording while you are at it ;-). – Peter - Reinstate Monica Jul 13 '15 at 12:28
  • 1
    I have no copy of K&R here. Did they really write that? The sentence is just not correct -- argv is a pointer to a _pointer array_. To call pointers strings is sloppy (the strings are sequences of chars). – Peter - Reinstate Monica Jul 13 '15 at 12:33
  • Yes change it. In an online copy of a paper of K&R (UNIX Programming —Second Edition, 1997) I found "an array argv of pointers to character strings that contain the arguments". That is exactly what it is. Check your source... – Peter - Reinstate Monica Jul 13 '15 at 12:41
  • Ok modifying it then. – Raman Jul 13 '15 at 12:50
  • A pointer to an array is something different than a pointer to an array's first element. – alk Jul 13 '15 at 13:00
  • Something completly different: As I have no recent K&R here, I cannot verfiy this, but if the picture is scan out of K&R remove it. It is copyrighted. – alk Jul 13 '15 at 13:03
  • This answer makes a lot more sense with that edit. Thanks. – Hugh McMaster Jul 13 '15 at 13:53
0

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. It will not affect execution other than what you do with it inside program.

Just remember argv is null terminated.

ameyCU
  • 16,489
  • 2
  • 26
  • 41
-6

The pointers that argv points to, and the characters in those pointers, are not writable by your application. Anything can happen if you modify them. Of course you are free to make a copy of the argv array, or use an array of bool, or whatever other method you prefer.

Just don't write to argv [i].

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • 2
    Since the spec says `The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program`, it means you can clearly modify the strings. – Hasturkun Jul 13 '15 at 11:23
  • @HughMcMaster What do you mean? Modifying `argv[x]` is ok; `argv[x][y]` is though undefined behavior. – edmz Jul 13 '15 at 11:49