为什么a和a的行为不同?

时间:2021-11-21 04:13:50

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

我认为a和a是一样的因为它们像指针一样工作。然而,我在以下代码中遇到了意想不到的事情:

#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

我发现这种行为很奇怪,所以我在摆弄这段代码。当我将a的类型从bool更改为int编译器时,总是会报告一个错误

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

Why does this work the way it does?

为什么会这样呢?

3 个解决方案

#1


2  

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

我认为a和a是一样的因为它们像指针一样工作。

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];?

b = new int[4]后会发生什么?

The new memory layout of b is something like this:

b新的内存布局是这样的:

   +----------+
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, f.e.)可以用作其在内存中的地址的快捷方式(实际上是第一个元素的地址)。下列表示法是等价的:

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的第一个元素(上面示例中的1)。

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.

[0]是int,而[0]是int *。这是完整的表格。另外两个是语言提供的快捷方式,以便使代码更容易阅读和理解。

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".

b是存储在b变量中的值(NULL或上面示例中的0xacf3de)。它是int *类型的值——存储int类型的内存地址。&b是存储b值的内存地址。它的类型是int **——指向int的指针;或“内存中存储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).

在某种程度上,指针和数组是可以互换的。正如您在上面看到的,涉及到一个公共数据类型:int *。它是b的类型(存储int的地址)和[0]的类型(也是int的地址)。

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

这意味着,在可以使用b的地方,可以使用a(简写为&a[0]),反之亦然。

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].

此外,如果可以使用*b,则可以使用*a。它是*和[0]的缩写,意思是“在一个[0]的地址(&)中存储的值”,实际上,它与[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 **).

但是,在可以使用&b的地方,不能使用& &代替;记住,&a和[0]是一样的,它的类型是int *(但是&b的类型是int **)。

#2


2  

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.

您不是在初始化数组,而是分配一个bool数组,然后隐式地将其转换为bool,将其赋值为[0]:该值应该为true,因为new的指针应该与0不同。这种隐式转换不适用于int:这就是为什么在更改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:

这里,您试图将动态分配的数组分配给a,换句话说,将指向数组bool*的指针分配给静态数组bool[0]:正如编译器所说,类型是不兼容的。静态数组A[]可以用作指针,例如在下面的代码中:

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.

但是指针不能像您正在尝试的那样转换成静态数组。

#3


0  

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

新类型[x]返回的值的类型是* i。e是那种类型的指针

examle: So Right syntax is bool a;

正确的语法是bool a;

*a = new bool[x];

* = 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

新的bool[x]语法错误,因为将指针赋给普通变量是无效的

see for more details

看到更多的细节

#1


2  

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

我认为a和a是一样的因为它们像指针一样工作。

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];?

b = new int[4]后会发生什么?

The new memory layout of b is something like this:

b新的内存布局是这样的:

   +----------+
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, f.e.)可以用作其在内存中的地址的快捷方式(实际上是第一个元素的地址)。下列表示法是等价的:

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的第一个元素(上面示例中的1)。

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.

[0]是int,而[0]是int *。这是完整的表格。另外两个是语言提供的快捷方式,以便使代码更容易阅读和理解。

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".

b是存储在b变量中的值(NULL或上面示例中的0xacf3de)。它是int *类型的值——存储int类型的内存地址。&b是存储b值的内存地址。它的类型是int **——指向int的指针;或“内存中存储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).

在某种程度上,指针和数组是可以互换的。正如您在上面看到的,涉及到一个公共数据类型:int *。它是b的类型(存储int的地址)和[0]的类型(也是int的地址)。

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

这意味着,在可以使用b的地方,可以使用a(简写为&a[0]),反之亦然。

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].

此外,如果可以使用*b,则可以使用*a。它是*和[0]的缩写,意思是“在一个[0]的地址(&)中存储的值”,实际上,它与[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 **).

但是,在可以使用&b的地方,不能使用& &代替;记住,&a和[0]是一样的,它的类型是int *(但是&b的类型是int **)。

#2


2  

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.

您不是在初始化数组,而是分配一个bool数组,然后隐式地将其转换为bool,将其赋值为[0]:该值应该为true,因为new的指针应该与0不同。这种隐式转换不适用于int:这就是为什么在更改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:

这里,您试图将动态分配的数组分配给a,换句话说,将指向数组bool*的指针分配给静态数组bool[0]:正如编译器所说,类型是不兼容的。静态数组A[]可以用作指针,例如在下面的代码中:

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.

但是指针不能像您正在尝试的那样转换成静态数组。

#3


0  

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

新类型[x]返回的值的类型是* i。e是那种类型的指针

examle: So Right syntax is bool a;

正确的语法是bool a;

*a = new bool[x];

* = 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

新的bool[x]语法错误,因为将指针赋给普通变量是无效的

see for more details

看到更多的细节