我一直在研究C ++进行测试,目前我仍然使用指针算法。
基本问题如下:
int numColumns = 3;
int numRows = 4;
int a[numRows][numColumns];
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1][0] = 4;
a[1][1] = 5;
a[1][2] = 6;
a[2][0] = 7;
a[2][1] = 8;
a[2][2] = 9;
a[3][0] = 10;
a[3][1] = 11;
a[3][2] = 12;
for (int i=numColumns-1; i>-1;i--)
{
cout << a[numRows-1][i] << endl;
}
一个非常简单的程序,它打印下面的“矩阵行”。即12,11,10。
现在我正在尝试使用int *。
进行等效我的同学告诉我的是这样的想法:
array[i][j] == p[numColumns*i+j]
如果这是正确的,那么以下内容不应该等同于我正在寻找的内容:
int* p = reinterpret_cast<int*> a;
for (int i=numColumns-1; i>-1;i--)
{
cout << p[numColumns*(numRows-1)+i] << endl;
}
感谢。
答案 0 :(得分:2)
int array[3][5]
不是int array[3*5]
的抽象(用C ++语言)。标准说二维数组(和一般的N维数组)是数组的数组。 array[3][5]
是一个由三个元素组成的数组,其中每个元素都是一个包含5个元素的数组(在本例中为整数)。 C ++的类型系统确实做出了这种区分。
根据C ++标准,数组T array[N]
是一个连续的内存块,包含类型为T的N个元素。这意味着一个多维数组,假设int array [3] [5]将是包含3个int[5]
数组的连续内存块,每个int[5]
数组是5 ints
的连续块。
在我的机器上,内存最终完全按照您的预期布局 - 与int array[3*5]
相同。然而,由于类型系统(区分int[]
和int[][]
),处理内存的方式不同。这就是为什么你需要使用reinterpret_cast
本质上告诉你的编译器“获取这个内存而不进行任何转换,将其视为这种新类型”的原因。
我不完全确定这种内存布局是否有保证。我无法在标准中找到任何表明数组无法填充的内容。如果它们可以填充(再次,我不确定)那么int[5]
数组实际上可能不是5个元素长(更好的例子是char[5]
,我可以看到填充到8个字节)。
int*
和int**
之间也存在明显的差异,因为后者并不能保证连续的记忆。
编辑:C ++区分int[3*5]
和int[3][5]
的原因是因为它想要保证内存中元素的顺序。在C ++中,int[0][1]
和int[0][2]
在内存中相距sizeof(int)
。但是,在Fortran中,int[0][0]
和int[1][0]
在内存中相距sizeof(int)
,因为Fortran使用列主要表示。
这是一个帮助解释的图表:
0 1 2
3 4 5
6 7 8
可以制成一个看起来像{0,1,2,3,4,5,6,7,8}的数组或一个看起来像这样的数组:{0,3,6,1,4,7 ,2,5,8}。
答案 1 :(得分:1)
提示:在原始代码中,a
的类型与int**
更相似,因此您不应将其转换为int*
。它是指向指针的指针。
如果你想像一维数组一样访问它,那么a
也必须被定义为一维数组。
答案 2 :(得分:0)
@rwong:真的吗?我认为多维数组只是我们的“抽象”,因为以下是等价的:
int array[3][5];
int array[3*5];
无论如何,我确定了什么是错的。像往常一样,这不是我的代码,而是复制粘贴某人的代码并从那里开始工作。
我的意思是:
for(int i=numRows-1; i>-1 ;i++)
{
cout << p[numColumns*numRows-1+i] << endl;
}
很有趣因为我没有从VS复制粘贴我的代码,但实际上是从头开始编写它来“说明”我的错误。
这里要学习的课程;)
编辑:我仍然不确定rwong在这里解释了什么。有人愿意详细说明吗?
答案 3 :(得分:0)
考虑它的另一种方式:由于a
类似于int**
,a
的一部分是否与int*
类似?