帮助指针算术

时间:2010-08-26 19:08:06

标签: c++ pointers

我一直在研究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;
}

感谢。

4 个答案:

答案 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*类似?