C11 5.1.2.2.1/2 says:
The parameters
argc
andargv
and the strings pointed to by theargv
array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.
My interpretation of this is that it specifies:
int main(int argc, char **argv) { if ( argv[0][0] ) argv[0][0] = 'x'; // OK char *q; argv = &q; // OK }
however it does not say anything about:
int main(int argc, char **argv) { char buf[20]; argv[0] = buf; }
Is argv[0] = buf;
permitted?
I can see (at least) two possible arguments:
argv
and argv[x][y]
but not argv[x]
, so the intent was that it is not modifiableargv
is a pointer to non-const
objects, so by in the absence of specific wording to the contrary, we should assume they are modifiable objects.The syntax char** argv declares argv to be a pointer to a pointer to a character, that is, a pointer to a character array (a character string)--in other words, an array of character strings. You could also write this as char* argv[] .
argv[n] is not a string; it's a pointer that points to the first character of a string. – M.M. Sep 9, 2014 at 5:54. 2.
argv is an array of strings, or say, an array of char * . So the type of argv[1] is char * , and the type of argv[1][0] is char .
The first (conventionally called argc) is the number of command-line arguments the program was invoked with; the second (argv) is a pointer to an array of character strings that contain the arguments, one per string.
IMO, code like argv[1] = "123";
is UB (using the original argv
).
"The parameters
argc
andargv
and the strings pointed to by theargv
array shall be modifiable by the program, and retain their last-stored values between program startup and program termination." C11dr & C17dr1 §5.1.2.2.1 2
Recall that const
came into C many years after C's creation.
Much like char *s = "abc";
is valid when it should be const char *s = "abc";
. The need for const
was not required else too much existing code would have be broken with the introduction of const
.
Likewise, even if argv
today should be considered char * const argv[]
or some other signature with const
, the lack of const
in the char *argv[]
does not complete specify the const
-ness needs of the argv
, argv[]
, or argv[][]
. The const
-ness needs would need to be driven by the spec.
From my reading, since the spec is silent on the issue, it is UB.
Undefined behavior is otherwise indicated in this International Standard by the words ‘‘undefined behavior’’ or by the omission of any explicit definition of behavior" §4 2
[edit]:
main()
is a very special function is C. What is allowable in other functions may or may not be allowed in main()
. The C spec details attributes about its parameters that given the signature int argc, char *argv[]
that shouldn't need. main()
, unlike other functions in C, can have an alternate signature int main(void)
and potentially others. main()
is not reentrant. As the C spec goes out of its way to detail what can be modified: argc
, argv
, argv[][]
, it is reasonable to question if argv[]
is modifiable due to its omission from the spec asserting that code can.
Given the specialty of main()
and the omission of specifying that argv[]
as modifiable, a conservative programmer would treat this greyness as UB, pending future C spec clarification.
If argv[i]
is modifiable on a given platform, certainly the range of i
should not exceed argc-1
.
As "argv[argc]
shall be a null pointer", assignining argv[argc]
to something other than NULL
appears to be a violation.
Although the strings are modifiable, code should not exceed the original string's length.
char *newstr = "abc"; if (strlen(newstr) <= strlen(argv[1])) strcpy(argv[1], newstr);
1 No change with C17/18. Since that version was meant to clarify many things, it re-enforces this spec is adequate and not missing an "argv
array elements shall be modifiable".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With