4

I don't understand what the difference between

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

and

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

is.

I'm aware of the difference between a char*[] and const char*[] but I wonder why one would like to use the latter.

Are there use cases where one would want to change command line arguments? What's the best practice about adding const?

the busybee
  • 10,755
  • 3
  • 13
  • 30
  • 1
    The only difference would be that const char does not allow you to modify the data. For example argv[0][0] = 'X'; will in that case throw a compiler error. – Sven Nilsson Dec 03 '22 at 14:58
  • @SvenNilsson: That is not the only difference. The behavior with `int main(int argc, char *argv[])` is defined by the C standard. The behavior with `int main(int argc, const char *argv[])` is not, because the types are not compatible and are not interchangeable as function parameter declarations or argument types. – Eric Postpischil Dec 03 '22 at 15:02

2 Answers2

6

int main(int argc, char *argv[]) is a defined way of declaring main for a hosted environment according to the C standard, per C 2018 5.1.2.2.1 1. int main(int argc, const char *argv[]) is not.

It is good to use const where applicable to indicate that the pointed-to objects will not change, but it must be used appropriately. The types char *[] and const char *[] are not compatible and are not interchangeable as parameter declarations or argument types. If main is declared with const char *argv[], the behavior is not defined by the C standard.

As for why the prescribed declaration is char *argv[] rather than const char *argv[], that is partly historical and partly because some techniques for processing command-line arguments modify the arguments in place.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • `char *argv[]` is a defined way of declaring, is it? I thought it's `const char **argv` since `argv` is immutable? – Marco Dec 03 '22 at 15:03
  • 4
    @marco-a: Neither `argv` nor the pointers it points to nor the strings they point to are immutable. C 2018 5.1.2.2.1 2 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.” – Eric Postpischil Dec 03 '22 at 15:05
  • that is interesting! I just learned something today. I always assumed it to be immutable. (possibly because of the bad practice of modifying user input). – Marco Dec 03 '22 at 15:06
2

The first one (char** argv) is defined by the C11 standard:

It shall be defined with a return type of int and with no parameters:

int main(void) { /* ... */ }

or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):

int main(int argc, char *argv[]) { /* ... */ }`

or equivalent¹⁰) or in some other implementation-defined manner.

¹⁰Thus, int can be replaced by a typedef name defined as int, or the type of argv can be written as char ** argv, and so on.

You could argue that const char is "equivalent" to char in the way the C11 standard is defining it. However, the standard also says this about the parameters:

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.

So it would seem const is not C standard.

This answer details if it's OK to modify main parameters. The array char **argv is allocated at runtime, and modifying it doesn't affect any program execution.

As to why const isn't used as a declaration, it mainly boils down to historical practices. This question's answers detail why const char **argv might be used instead of its non-const.

human bean
  • 847
  • 3
  • 15