Marko Divjak
Marko Divjak

Reputation: 31

Why do a[] and *a behave differently?

I thought a[] and *a are the same thing because they work like pointers. Yet I encountered something unexpected in the following code:

#include <iostream>
using namespace std;

class F {
public:
    bool a[];
    F();
};

F::F() {
    *a = new bool[5];
    a[2] = true;
}

int main() {
    F obj;
    if(obj.a[2])
        cout << '?';
    return 0;
}

This code prints ?, but I don't understand how it works. When:

*a = new bool[5];

is changed into:

a = new bool[5];

compiler reports:

F:\main.cpp|11|error: incompatible types in assignment of 'bool*' to 'bool [0]'|

I found this behaviour weird, so I was playing around with this code. When I changed the type of a from bool to int compiler always reports an error

F:\main.cpp|11|error: invalid conversion from 'int*' to 'int' [-fpermissive]|

Why does this work the way it does?

Upvotes: 2

Views: 119

Answers (3)

Shashi Kundan
Shashi Kundan

Reputation: 363

Type of value returned from new Type[x] is Type * i.e pointer of that type

examle: So Right syntax is bool a;

*a = new bool[x];

so it is wrong to do like is

a=new bool[x] wrong syntax as it is invalid to assign pointer to a normal varibale

see for more details

Upvotes: 0

axiac
axiac

Reputation: 72226

I thought a[] and *a are the same thing because they work like pointers.

Let's talk about this piece of declaration:

int a[4] = { 1, 2, 3, 5 };
int *b = NULL;

This is how they land in memory in the executable:

   +----+----+----+----+
a: |  1 |  2 |  3 |  5 |        <-- 4 integers
   +----+----+----+----+

   +----------+
b: |   NULL   |                   <-- 1 pointer that points to nowhere
   +----------+

As you can see, they are not the same thing.

What happens after b = new int[4];?

The new memory layout of b is something like this:

   +----------+
b: | 0xacf3de |               <-- 1 pointer that points to a block of 4 integers
   +----------+

Somewhere else in memory (at address 0xacf3de)...

          +----+----+----+----+
0xacf3de: |  ? |  ? |  ? |  ? |         <-- 4 integers
          +----+----+----+----+

But wait, somebody told me that arrays work like pointers...

No, that's not true. The arrays do not work like pointers.

An array name (a, f.e.) can be used as a shortcut for its address in memory (which is, in fact, the address of its first element). The following notations are equivalent:

a
&a
&a[0]

The value of all of them is the address in memory where the first element of a (the 1 in the example above) is stored.

a[0] is an int, &a[0] is an int *. This is the complete form. The other two are shortcuts that the language provides in order to make the code easier to read and understand.

The things are different for pointers.

b is the value stored in the b variable (NULL or 0xacf3de in the example above. It is a value of type int * -- the address in memory where an int is stored. &b is the address in memory where (the value of) b is stored. Its type is int ** -- a pointer to a pointer to an int; or "the address in memory where is stored the address of an int".

But wait, they can be replaced one for another in some contexts

Up to some point, yes, a pointer and an array are interchangeable. As you can see above, there is a common data type involved: int *. It is the type of b (which stores the address of an int) and also the type of &a[0] (which is also the address of an int).

This means that where b can be used, a (a short of &a[0]) can be used instead, and vice-versa.

Also, where *b can be used, *a can be used instead. It is the short for *&a[0] and it means "the value (*) stored at the address (&) of a[0]" and it is, in fact, the same as a[0].

But, where &b can be used, &a cannot be used instead; remember that &a is the same as &a[0] and its type is int * (but the type of &b is int **).

Upvotes: 2

rocambille
rocambille

Reputation: 15976

The line:

*a = new bool[5];

is equivalent to:

a[0] = new bool[5];

You are not initialiazing your array, but allocating an array of bool which is then implicitly converted into bool to be assigned to a[0]: the value should be true since the pointer returned by new should be different from 0. This implicit conversion does not apply with ints: that is why you are getting an error when changing the type of a.


Now, considering this line:

a = new bool[5];

Here you are trying to assign your dynamically allocated array to a, in other words assigning a pointer to an array bool* to a static array bool[0]: as the compiler says, the types are incompatible. A static array a[] can be used as a pointer, e.g. in the following code:

int foo(bool* a) { /* ... */ }

bool my_array[5];
foo(my_array);

But pointers can not be converted into static arrays as you are trying to do.

Upvotes: 2

Related Questions