Are the strings in argv modifiable?
Asked Answered
R

2

31

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 parameter to uppercase.

I know that you shouldn't modify string literals as it can cause undefined behavior, so was just wondering if the strings in the *argv[] are literals that you shouldn't change.

int main(int argc, char *argv[])
Ribera answered 30/1, 2016 at 14:24 Comment(7)
Possible duplicate of What are the arguments to main() for?Ultrafilter
It is not a literal. You can change it.Norseman
I know what they are for and what they mean, just wondering if they were literals.Ribera
@Ultrafilter Not a duplicate. That question doesn't mention anything about string literals.Calculating
If you didn't write a string in your program, and wrap it in quotes, it's not a string literal.Teacher
@JonathonReinhart oh wow I did not know that, thanks!Ribera
Compiled code does not have string literals. As much as integer constants, keywords and operators, they are syntax elements in the source code.Berlioz
M
28

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!

Minify answered 30/1, 2016 at 14:27 Comment(13)
Thanks for your answer, I know it always causes undefined behavior I guess I should make my question more explicit, I'll change it now.Ribera
That this imply that the pointers themselves can be modified or not? I.e. can one do: argv[0] = NULL Guzel
@Guzel Good question. IMO, "The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program [...]" only refers to argc and argv themselves and the strings. I'll dig somewhat and report back.Minify
@cad: there is not anything on where these strings should be stored, right? As far as the local program goes, its arguments may come from a hardcoded string in a ROM. Also, making them longer should be out of the question. So you can safely change the pointers (because local) but not the strings themselves (because external).Augmented
@Augmented As far as I can tell, the first quotation directly contradicts that: "[...] the strings pointed to by the argv array shall be modifiable by the program [...]," so, except if the arguments are copied from ROM, they cannot be stored in read-only memory. Or does "the strings" refer to the pointers themselves? IMO, it does not.Minify
@Guzel I didn't find anything sensible, so I'll just pretend, accordingly to § 4/1 (same standard as in my answer): "Undefined behavior is otherwise indicated [...] by the omission of any explicit definition of behavior." Doesn't mean I'm right, tho.Minify
@cad I just noticed it says right there: The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program. => The parameters shall be modifiable.Guzel
@Guzel Of course I can. :P But it only talks about the arguments themselves and the strings, not about the pointers to the strings.Minify
Isn't that the same thing? I think it is. By pointers I means the values in the parameter argv at certain indexes, and I gave the example argv[0]. So it is defined to do argv[0] = NULL.Guzel
@Guzel IMO, a string is the actual string of characters (a character being argv[0][0] for example), not the pointer to them. But anyway, if "string" refers to the pointers, what about the actual characters?Minify
@cad A string is defined as a contiguous sequence of characters terminated by a null character. I think you can modify everything, otherwise the text would be more specific, but I'm not 100% sure about the pointers themselves.Guzel
I'm pretty sure the argv[argc] == NULL-thing is a guarantee from the environment, not a prohibition on modification by the program.Situla
@Guzel I asked a question regarding that, just so that you know.Minify
A
3

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
Arne answered 31/1, 2016 at 10:28 Comment(1)
Thanks for this! Yeah I wasn't really increasing or decreasing the size just changing a character to be upper or lower case.Ribera

© 2022 - 2024 — McMap. All rights reserved.