在C中用x/y坐标索引2D数组的惯例是什么?
我一直在编写一个小程序,在这个程序中,我必须使用船上的坐标系(2d数组中的x/y),并在考虑是否应该使用像在C中用x/y坐标索引2D数组的惯例是什么?,c,arrays,coordinates,C,Arrays,Coordinates,我一直在编写一个小程序,在这个程序中,我必须使用船上的坐标系(2d数组中的x/y),并在考虑是否应该使用像array[x][y]这样的索引,这对我来说似乎更自然,或者array[y][x]这样的索引会更好地匹配数组在内存中的表示方式。我相信如果我保持一致,这只是命名问题,那么这两种方法都会起作用,但是编写更大程序时的约定呢?在我的领域(图像处理)[y][x]约定更为常见。无论你做什么,都要保持一致并把它做好。 你也应该考虑你将如何处理这些数组,以及这是否是时间的关键。 如评论中所述:a[r][c
array[x][y]
这样的索引,这对我来说似乎更自然,或者array[y][x]
这样的索引会更好地匹配数组在内存中的表示方式。我相信如果我保持一致,这只是命名问题,那么这两种方法都会起作用,但是编写更大程序时的约定呢?在我的领域(图像处理)[y][x]
约定更为常见。无论你做什么,都要保持一致并把它做好。 你也应该考虑你将如何处理这些数组,以及这是否是时间的关键。
如评论中所述:a[r][c+1]
元素就在a[r][c]
的旁边。当迭代较大的数组时,这一事实可能会对性能产生相当大的影响。正确的遍历顺序将导致缓存线被充分利用:当访问一个数组索引时,认为“很可能”之后将访问下一个索引,并将整个内存块加载到缓存中。如果之后访问的是完全不同的内存位置(即,下一行中的一个),则该缓存带宽将被浪费
如果可能,您应该尝试使用适合实际内存布局的遍历顺序
(当然,这在很大程度上与“约定”和“习惯”有关:当编写像a[row][col]
这样的数组访问时,这通常被解释为数组访问a[y][x]
,因为x轴是水平的,y轴是垂直的约定…)
下面是一个小示例,演示了“错误”遍历顺序对性能的潜在影响:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
float computeSumRowMajor(float **array, int rows, int cols)
{
float sum = 0;
for (int r=0; r<rows; r++)
{
for (int c=0; c<cols; c++)
{
sum += array[r][c];
}
}
return sum;
}
float computeSumColMajor(float **array, int rows, int cols)
{
float sum = 0;
for (int c=0; c<cols; c++)
{
for (int r=0; r<rows; r++)
{
sum += array[r][c];
}
}
return sum;
}
int main()
{
int rows = 5000;
int cols = 5000;
float **array = (float**)malloc(rows*sizeof(float*));
for (int r=0; r<rows; r++)
{
array[r] = (float*)malloc(cols*sizeof(float));
for (int c=0; c<cols; c++)
{
array[r][c] = 0.01f;
}
}
clock_t start, end;
start = clock();
float sumRowMajor = 0;
for (int i=0; i<10; i++)
{
sumRowMajor += computeSumRowMajor(array, rows, cols);
}
end = clock();
double timeRowMajor = ((double) (end - start)) / CLOCKS_PER_SEC;
start = clock();
float sumColMajor = 0;
for (int i=0; i<10; i++)
{
sumColMajor += computeSumColMajor(array, rows, cols);
}
end = clock();
double timeColMajor = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("Row major %f, result %f\n", timeRowMajor, sumRowMajor);
printf("Col major %f, result %f\n", timeColMajor, sumColMajor);
return 0;
}
#包括
#包括
#包括
float computeSumRowMajor(浮点**数组、整数行、整数列)
{
浮点数和=0;
对于(int r=0;rAs,只要你是一致的,这就不重要了,但是有两种情况我认为array[y][x]
会有帮助。1)字符串数组,你可能需要处理一维array[y]
。2)图像数组,你可能需要扫描光栅线。我更喜欢array[y][x]
带有嵌套的处理循环for(y…)for(x…)
。数组是行主数组,因此a[0][1]
是a[0][0]
之后的下一个内存位置。选择适合您的程序的任何方式。[y][x]更自然的语言是[y][x]
Use@chux-关于这一点我需要思考。很好。