C++数组指针

C++ array pointer

本文关键字:指针 数组 C++      更新时间:2023-10-16

我遇到了这样的C++程序

#include<iostream>
using namespace std;
int main() {
int N = 10;
int M = 2;
int a[] = { 2,1,4,3,6,5,8,7,10,9 };
int(*b)[5] = (int(*)[5]) a;
for (int i = 0; i<M; i++) {
for (int j = 0; j<N / M; j++) {
cout << b[i][j] << endl;
}
}
system("pause");
return 0;
}

上述程序的输出为2,1,4,3,6,5,8,7,10,9。看起来b是一个数组点。那么(int(*)[5]) a是什么意思呢?有人可以帮我解释一下吗?

a是一个包含 10 个元素的 int-array :int [10]b是一个指向包含 5 个元素的 int-array 的指针:int (*) [5]b使用a的值初始化,并使用 C 样式强制转换显式转换:(int(*)[5]) a

实际上a是一个1x10的矩阵,b是一个2x5的矩阵,它实际上是a的"重塑"为b,具有相同的内容。这里"最"危险的事情是重塑不执行深度复制,即对b的更改也会影响a,反之亦然;

这里int的类型是完全无关紧要的。这是一个在线示例,具有几种不同的类型。

语句

int a[] = { 2,1,4,3,6,5,8,7,10,9 };

在记忆中看起来像这样

+---+---+---+---+---+---+---+---+---+---+
a -> | 2 | 1 | 4 | 3 | 6 | 5 | 8 | 7 | 10| 9 |;
+---+---+---+---+---+---+---+---+---+---+
+0  +1 ...  

当您访问数组中的元素时,您通常使用 [],但由于a是一个地址。 您可以访问 元素也使用指针样式偏移

a + 2   // address to third int, *(a+2) the actual value `3`

现在,通过声明另一种访问 10 个整数的方法,您可以以不同的方式访问a的内存,类型决定了您访问内存的方式

int(*b)[5] = (int(*)[5]) a; // compiler, pretend a is of same type

在上面的语句中,ba指的是相同的内存,但b的类型是指向 int 数组的 5

。由于b是一个指针:

b指向a开始的地方。 做b++,b现在指向数组a中间,因为B的声明说它只包含五个整数

所以

b[0] points to address a + 0
b[0][0] is the value of a + 0 or a[0] alt. *(a + 0)
b[1] points to address a + 5 
b[1][0] is the value of a + 5 or a[5] alt. *(a + 5)

由于 C 通常不会检查您是否越界,因此上述工作正常。

由于b是指向 5 个整数数组的指针,因此:

  • b[0]将指向一个由 5 个整数组成的数组,这些整数从b指向的位置存储。
  • b[1]将指向一个由 5 个整数组成的数组,这些整数从b + (5*sizeof(int))指向的位置存储。

由于b已通过类型转换int(*b)[5] = (int(*)[5]) a;分配了a地址,因此:

  • b[0]将指向数组的前 5 个整数aa[0..4]
  • b[1]将指向数组a的下一个 5 个整数,即a[5..9]

现在

  • b[0][0]将给出在b[0]指向的数组0索引的第一个元素的值,即a[0]
  • b[0][1]将给出在b[0]指向的数组1处索引的第二个元素的值,即a[1]

..

..

  • b[1][0]将给出第一个元素的值,该元素b[1]指向的数组0处索引,即a[5]
  • b[1][1]将给出在b[1]指向的数组1处索引的第二个元素的值,即a[6]

在这里,a[]是一个由 10 个整数组成的数组。b是指向 5 个元素数组的指针。

int(*b)[5] = (int(*)[5]) a;

在上面的语句中,数组a[]的地址被类型转换为指向 5 个元素数组的指针。然后,b作为二维数组进行访问。

Int-array a 被显式初始化为包含 10 个元素。变量 a 的内部表示形式是指向第一个元素的指针。写 a[3] 是"给我偏移量为 3 的 a 的内容"。

然后将变量 b 创建为指向 int 的指针数组(长度为 5)(它不是"点",而是"指针",顺便说一句)。 b 使用 a 的内容进行初始化,但由于 a 属于不同的类型,因此必须将其类型转换为正确的类型(即 b 的类型)。类型转换基本上意味着"假装变量 a 的内存是不同类型的"。这是用c型演员表完成

(int(*)[5]) a

总而言之,我不会努力复制这种编码风格。

此外,以下代码仅在指向 int 的指针是 int 大小的两倍时才有效,例如 64 位指针、32 位 int。 肮脏、肮脏的代码。