简体   繁体   中英

The parameters of the Main function in C++

When I try to compile this code, an error appears :

#include<iostream>
using namespace std;

int main()
{
    char* p = "Hello";
    return 0;
}

error C2440: 'initializing': cannot convert from 'const char [6]' to 'char *'

This error is fixed when I add the word const in the declaration of p .

This code compiles and runs:

#include<iostream>
using namespace std;

int main()
{
    const char* p = "Hello";
    return 0;
}

So my question is : How is the main() function able to take char *argv[] (as a parameter) and not const char *argv[] (as a parameter)?

int main (int argc, char *argv[])

"Hello" is a string literal, which has a type of const char[6] . You can't set a non-const char* pointer to point at a const char[] , hence the error. Doing so would grant the caller access to mutate read-only data.

The char* pointers in the argv[] parameter of main() are pointing at char[] arrays which are allocated and filled dynamically at runtime, when the program's startup code parses the calling process's command line parameters before calling main() . They are not pointing at string literals, and thus do not need to be const char* .

TL;DR: You can actually mutate argv , string literals are immutable in c++. eg:

#include <iostream>

int main(int, char** argv) {
  char* p = new char[3];
  p[0] = 'H'; p[1] = 'i'; p[2] = 0;
  argv[0][0] = ':';
  argv[0][1] = 'P';
  argv[0][2] = '\n';
  std::cout << p << argv[0];
  delete[] p;
}

Same code on Compiler Explorer

This is, as far as I know, valid c++, with well-defined behavior.
char* x = "An immutable char const[]."; is not.
You can probably cast const away with const_cast .
But any attempt to modify the string pointed to by x would cause undefined behavior.

Let's see what is happening in your example on case by case basis:

Case 1

Here we consider the statement:

char* p = "Hello";

On the right hand side of the above statement, we've the string literal "Hello" which is of type const char[6] . There are two ways to understand why the above statement didn't work.

  1. In some contexts, const char[6] decays to a const char* due to type decay . This basically means that on the right hand side we will have a const char* while on the left hand side we have a char* . Note also that this means that on the right hand side we've a low-level const but on the left hand side we don't have any low-level const. So, the given statement won't work. For the statement to work we've to make sure that the left hand side should've either same or greater low-level const qualifier than the right hand side.

A few example would illustrate the point:

int arr1[] = {1,2,3};
int* ptr1 = arr1; //this works because arr1 decays to int* and both sides have no low level const

const int arr2[] = {1,2,3};
int* ptr2 = arr2; //won't work, right hand side will have a low level const(as arr2 decays to const char*) while the left hand side will not have a low level const

const int* ptr3 = arr2; //this works, both side will have a low level const
  1. The second way(which is basically equivalent to the 1st) to understand this is that since "Hello" is of type const char[6] , so if we are allowed to write char* p = "Hello"; then that would mean that we're allowed to change the elements of the array. But note that the type const char[6] means that the char elements inside the array are immutable(or non-changable). Thus, allowing char* p = "Hello"; would allow changing const marked data, which should not happen(since the data was not supposed to change as it was marked const ). So to prevent this from happening we have to use const char* p = "Hello"; so that the pointer p is not allowed to change the const marked data.

Case 2

Here we consider the declaration:

int main (int argc, char *argv[])

In the above declaration, the type of the second parameter named argv is actually a char** . That is, argv is a pointer to a pointer to a char . This is because a char* [] decays to a char** due to type decay . For example, the below given declarations are equivalent:

int main (int argc, char *argv[]); //first declaration
int main (int argc, char **argv);  //RE-DECLARATION. Equivalent to the above declaration

In other words, argv is a pointer that points to the first element of an array with elements of type char* . Moreover, each elements argv[i] of the array(with elements of type char* ) itself point to a character which is the start of a null terminated character string. That is, each element argv[i] points to the first element of an array with elements of type char (and not const char ). Thus, there is no need for const char* . A diagram is given for illustration purposes:

argc 和 argv

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM