Are the strings in argv modifiable?

前端 未结 2 1076
孤街浪徒
孤街浪徒 2020-12-18 17:36

I just wrote a small program that reads command line arguments in C, nothing too difficult. I was also modifying them, for example changing the first character of the parame

相关标签:
2条回答
  • 2020-12-18 18:21

    From the C11 standard draft N1570, §5.1.2.2.1/2:

    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.

    They are modifiable. That means they are not string literals.

    But be careful: the upper citation only refers to pointers to strings, excluding the obligatory null pointer at argv[argc]1.
    From the C11 standard draft N1570, §5.1.2.2.1/2 (same as above)1:

    argv[argc] shall be a null pointer


    Notes:

    • Something regarding this sentence:

      I know that you shouldn't modify string literals as it can cause undefined behavior [...]

      "can"? It does always. Undefined behavior includes expected, as if well-defined, and unexpected behavior.


    1 Thanks to @black!

    0 讨论(0)
  • 2020-12-18 18:39

    The arrays that support the strings in argv are modifiable.
    But you have no way to know their sizes.

    I would frown upon seeing code that (tries to) increase the size of the strings.

    #include <stdio.h>
    #include <string.h>
    // this program may behave erraticaly
    int main(int argc, char **argv) {
        for (int k = 1; k < argc; k++) {
            printf("original argv[%d] is %s\n", k, argv[k]);
        }
        printf("\n");
        for (int k = 1; k < argc; k++) {
            strcat(argv[k], " foo"); // add foo to each argv string
            printf("first modification to argv[%d] is %s\n", k, argv[k]);
        }
        printf("\n");
        for (int k = argc; k > 1; k--) {
            strcat(argv[k - 1], " bar"); // add bar to each argv string
            printf("final argv[%d] is %s\n", k - 1, argv[k - 1]);
        }
        return 0;
    }
    

    On my machine, calling that program with one two three arguments produces

    original argv[1] is one
    original argv[2] is two
    original argv[3] is three
    
    first modification to argv[1] is one foo
    first modification to argv[2] is foo foo
    first modification to argv[3] is foo foo
    
    final argv[3] is foo foo bar
    final argv[2] is foo foo foo bar bar
    final argv[1] is one foo foo foo bar bar bar
    
    0 讨论(0)
提交回复
热议问题