Natsu
Natsu

Reputation: 71

What is difference between char* and int* data type to create array of pointers in C++?

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

Answers (4)

NathanOliver
NathanOliver

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

Jonathan Mee
Jonathan Mee

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

Aconcagua
Aconcagua

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

majk
majk

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

Related Questions