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[])
CodePudding user response:
"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[]
, hense 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*
.
CodePudding user response:
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.
- In some contexts,
const char[6]
decays to aconst char*
due to type decay. This basically means that on the right hand side we will have aconst char*
while on the left hand side we have achar*
. 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
- The second way(which is basically equivalent to the 1st) to understand this is that since
"Hello"
is of typeconst char[6]
, so if we are allowed to writechar* p = "Hello";
then that would mean that we're allowed to change the elements of the array. But note that the typeconst char[6]
means that thechar
elements inside the array are immutable(or non-changable). Thus, allowingchar* p = "Hello";
would allow changingconst
marked data, which should not happen(since the data was not supposed to change as it was markedconst
). So to prevent this from happening we have to useconst char* p = "Hello";
so that the pointerp
is not allowed to change theconst
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 a dynamically allocated array with elements of type char*
. Moreover, each elements argv[i]
of the dynamically allocated array(with elements of type char*
) itself point to a character which is the start of a(dynamically allocated) null terminated character string. That is, each element argv[i]
points to the first element of a dynamically allocated 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: