Reputation: 71
While creating an array of pointers for int
data type the following code works:
int var[] = {10, 100, 200, 1000};
int *ptr[] = {&var[0], &var[1], &var[2], &var[3]};
While creating an array of pointers for char
data type the following is legal:
char *names[] = {"Mathew Emerson", "Bob Jackson"};
But if I create an array of pointers for int
data type as follows:
int var[] = {10, 100, 200, 1000};
int *ptr[] = {var[0], var[1], var[2], var[3]};
I get a compiler error. I understand why I am getting a compilation error in the above method of declaration for array of int
data type, as var[i] is not a reference to a variable to which a pointer must point to i.e. its address, but shouldn't I also get error by the same logic in the declaration of my char
array of pointer.
What is the reason that its is acceptable in char
array of pointers?
Is " a string value " an address of something to which a pointer can point to or is it just a const string value.
Upvotes: 5
Views: 234
Reputation: 180510
char *names[] = {"Mathew Emerson", "Bob Jackson"};
Is not legal in C++. A string literal has the type of const char[]
so it is illegal to store it as a char*
as it violates const-correctness. Some compilers allow this to still compile as a legacy from C since string literals have the type char[]
but it is not standard C++. If you turn up the warnings on your compiler you should get something along the lines of
main.cpp: In function 'int main()':
main.cpp:5:53: warning: ISO C++ forbids converting a string constant to 'char*' [-Wpedantic]
char *names[] = {"Mathew Emerson", "Bob Jackson"};
If you want an array of strings then I suggest you use a std::string
like
std::string names[] = {"Mathew Emerson", "Bob Jackson"};
The reason
char *names[] = {"Mathew Emerson", "Bob Jackson"};
"works" is that since the string literals are arrays they implicitly decay to pointers so
{"Mathew Emerson", "Bob Jackson"}
Becomes
{ address_of_first_string_literal, address_of_second_string_literal}
and then those are used to initialize the pointers in the array.
int *ptr[] = {var[0], var[1], var[2], var[3]};
Cannot work because var[N]
is a reference to the int
in the array and not a pointer.
Upvotes: 7
Reputation: 38919
Your misconception is wrapped up in your interpretation of what is represented by: "Mathew Emerson"
This is an array of characters that will be instantiated in read only memory as part of your program's bootstrapping. This array of characters is called a String Literal, specifically a:
Narrow multibyte string literal. The type of an unprefixed string literal is
const char[]
NathanOliver's answer correctly describes that your compiler doesn't have the warning level turned up high enough so it is allowing the, const char[]
to decay into a char*
. This is very bad because:
Attempting to modify a string literal results in undefined behavior: they may be stored in read-only storage (such as .rodata) or combined with other string literals[1]
It would have been completely legal and logical to do this however: const char *names[] = {"Mathew Emerson", "Bob Jackson"}
Hopefully that clarifies for you what's happening well enough for you to understand that working with a String Literal is working with a pointer. Your code: int *ptr[] = {var[0], var[1], var[2], var[3]}
is then illegal because, var[0]
is an int&
not an int*
. It would be similarly illegal to do: char* ptr = {names[0][0], names[0][1], names[0][2], names[0][3]}
Again the problem here would be that I was working with char&
s not char*
s.
Upvotes: 1
Reputation: 25526
(Ignoring the const-ness problem as mentioned in other answers...)
Each string literal you write ("Mathew Emerson"
, "Bob Jackson"
, ...) requires some storage location in the compiled code later.
It is as if you had written somewhere
char const[] MathewEmerson = { 'M', 'a', /*...*/, 'o', 'n', 0 };
So you you could construct your char const* array then as:
char const* names[] = { &MathewEmerson[0], /*...*/ };
As for arrays, the address of the array itself and its first element is the same, and arrays are implicitely converted to pointers, you can write instead
char const* names[] = { MathewEmerson, /*...*/ };
All this is done implicitely for you, if you use string literals.
Similarly, you could have written:
int *ptr[] = {var, &var[1], &var[2], &var[3]};
(note: var
, not &var[0]
for the first item) and if we go further, even:
int *ptr[] = {var, var + 1, var + 2, var + 3};
The result always would have been the same. Readability, understandability of one variant vs another? Well, another topic...
Upvotes: 1
Reputation: 857
"Mathew Emerson" is of type const char*
- it is already a pointer, thus you can directly store it in an array of pointers. The reason you need &
for the int case is to "convert" int
to int*
.
Upvotes: 1