我一直在寫一個小程序,其中我必須使用座標系統(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. C#二維數組索引交換
- 2. Python索引二維數組
- 3. 將一維數組索引轉換爲二維數組索引
- 4. 定義和索引到一個二維數組中 - C
- 5. 索引NumPy的二維數組與另一二維數組
- 6. 在numpy中用3d數組索引一個二維數組
- 7. python中的二維數組索引值
- 8. C++二維數組索引與1參數(爲什麼這個工作?)
- 9. 把二維數組中的三維世界座標
- 10. 將二維數組索引轉換爲一維索引
- 11. 在目標c中的二維數組搜索
- 12. 通二維數組引用
- 13. 目標中的二維數組C
- 14. 目標C中的二維數組
- 15. 二維索引 - 數組超出範圍
- 16. 1索引與二維數組錯誤
- 17. 改變二維數組的索引
- 18. numpy的 - 二維數組索引
- 19. 將一維數組的索引轉換爲二維數組
- 20. 馬平二維數組與索引的一個維數組
- 21. IndexError索引的二維數組與一維數組(NumPy的)
- 22. 二維數組的目標C從C#
- 23. 引用一維二維數組
- 24. Flex Sprite xy座標
- 25. 在LabVIEW中對沒有for循環的n維二維數組進行索引
- 26. C++二維數組
- 27. C++中的二維數組
- 28. C++中的二維數組
- 29. c中的二維數組#
- 30. 索引不規則網格在一維數組中的X,Y,Z座標
只要你一致,它應該沒有關係,但有兩種情況我可以想到'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