我一直在寫一個小程序,其中我必須使用座標系統(x/y在二維數組中),並且正在考慮是否應該使用像array[x][y]
這樣的索引,這對我來說似乎更自然,或者可以更好地匹配array[y][x]
數組在內存中的表示方式。如果我保持一致並且只是命名問題,我相信這兩種方法都可以工作,但編寫大型程序時慣例如何?在C中用x/y座標索引二維數組有什麼約定?
10
A
回答
7
在我的領域(圖像處理)[y][x]
約定更爲常見。無論你做什麼,都要保持一致並將其記錄在案。
2
您還應該考慮您將對這些陣列做什麼,以及這是否對時間至關重要。
正如在評論中提到的:元素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;
}
(道歉我違反了一些最佳實踐在這裏,我是usua lly一個Java人......)
對我來說,行主要訪問幾乎比列主要訪問快一個數量級。當然,確切的數字將會是沉重取決於目標系統,但所有目標的一般問題應該是相同的。
相關問題
- 1. 在相對於特定數組座標的二維數組中打印索引?
- 2. 基於函數的索引XY座標
- 3. XY座標的約束
- 4. 索引二維數組由索引的二維數組沒有循環
- 5. C++二維數組索引錯誤
- 6. C#二維數組索引交換
- 7. Python索引二維數組
- 8. 將一維數組索引轉換爲二維數組索引
- 9. 定義和索引到一個二維數組中 - C
- 10. 三維繪圖:爲什麼座標參數輸入爲二維數組?
- 11. 索引NumPy的二維數組與另一二維數組
- 12. 在numpy中用3d數組索引一個二維數組
- 13. java中二維數組的索引
- 14. matlab中二維數組的索引
- 15. python中的二維數組索引值
- 16. 蟒蛇從二維數組到三維座標數組
- 17. C++二維數組索引與1參數(爲什麼這個工作?)
- 18. 用二維數組對三維numpy數組進行索引
- 19. 匹配二維數組中的座標的有效方法
- 20. 使用二維數組在C++中進行二進制搜索
- 21. 將二維數組索引轉換爲一維索引
- 22. 把二維數組中的三維世界座標
- 23. 在目標c中的二維數組搜索
- 24. 在二維數組中找到有效的鄰居索引
- 25. 目標C中的二維數組
- 26. 目標中的二維數組C
- 27. 通二維數組引用
- 28. 如何「標記」二維數組中的索引位置?
- 29. 從二維數組獲得索引
- 30. 改變二維數組的索引
只要你一致,它應該沒有關係,但有兩種情況我可以想到'array [y] [x]'會在哪裏幫助。 1)一個字符串數組,你可能想要處理1-d'array [y]'。 2)一個圖像陣列,您可能想要掃描一條光柵線。對於(x ...)',我更喜歡'嵌套處理循環的數組[y] [x]'。 – 2014-12-06 23:47:35
數組是行優先的,所以'a [0] [1]'是'a [0] [0]'之後的下一個內存位置。選擇適合您程序的方式。 – 2014-12-07 01:08:22
。語言的自然更多是它['y] [x]'使用 – chux 2014-12-07 04:51:10