C++ 多维数组中的数组偏移计算(列与行主)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/789913/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
array offset calculations in multi dimensional array (column vs row major)
提问by mrwes
A textbook I recently read discussed row major & column major arrays. The book primarily focused on 1 and 2 dimensional arrays but didn't really discuss 3 dimensional arrays. I'm looking for some good examples to help solidify my understanding of addressing an element within a multi-dimensional array using row major & column major arrays.
我最近阅读的一本教科书讨论了行主要和列主要数组。这本书主要关注一维和二维数组,但并没有真正讨论 3 维数组。我正在寻找一些很好的例子来帮助巩固我对使用行主数组和列主数组在多维数组中寻址元素的理解。
+--+--+--+ | / / / /| | +--+--+--+ + | +---+---+---+---+ / / / /|/| | / / / / /| +--+--+--+ + + | +---+---+---+---+ + / / / /|/|/| | / / / / /|/| +--+--+--+ + + + | +---+---+---+---+ + + / / / /|/|/|/| | / / / / /|/|/| +--+--+--+ + + + + | +---+---+---+---+ + + + / / / /|/|/|/|/ | |000|001|002|003|/|/|/| +--+--+--+ + + + + | +---+---+---+---+ + + + |00|01|02|/|/|/|/ | |004|005|006|007|/|/|/| +--+--+--+ + + + | +---+---+---+---+ + + + |03|04|05|/|/|/ | |008|009|00A|00B|/|/|/ +--+--+--+ + + | +---+---+---+---+ + + |06|07|08|/|/ | |00C|00D|00E|00F|/|/ +--+--+--+ + | +---+---+---+---+ + |09|0A|0B|/ | |010|011|012|013|/ +--+--+--+ | +---+---+---+---+ arr[5][3][4] | arr[3][4][5]
NOTE:Original question incorrectly represented arr[3][4][5]. I have learned that the original subscript represents depth. The data has been corrected to reflect intended array representation.
注意:原始问题错误地表示 arr[3][4][5]。我了解到原始下标代表深度。数据已更正以反映预期的阵列表示。
Example hex data +---+---+---+---+ +---+---+---+---+ +---+---+---+---+ |000|001|002|003| |100|101|102|103| |200|201|202|203| +---+---+---+---+ +---+---+---+---+ +---+---+---+---+ |004|005|006|007| |104|105|106|107| |204|205|206|207| +---+---+---+---+ +---+---+---+---+ +---+---+---+---+ |008|009|00A|00B| |108|109|10A|10B| |208|209|20A|20B| +---+---+---+---+ +---+---+---+---+ +---+---+---+---+ |00C|00D|00E|00F| |10C|10D|10E|10F| |20C|20D|20E|20F| +---+---+---+---+ +---+---+---+---+ +---+---+---+---+ |010|011|012|013| |110|111|112|113| |210|211|212|213| +---+---+---+---+ +---+---+---+---+ +---+---+---+---+ slice 0 slice 1 slice 2 short Arr[3][4][5]; // assume array is filled with hex test data arr[1][2][3] = 0x10B use slice 1, row 2, col 3 arr[2][3][4] = 0x210 use slice 2, row 3, col 4 resolves to row 4, col 0
row major
{000,001,002,003,004,005,006,007,008,009,00A,00B,00C,00D,00E,00F,010,011,012,013,
100,101,102,103,104,105,106,107,108,109,10A,10B,10C,10D,10E,10F,110,111,112,113,
200,201,202,203,204,205,206,207,208,209,20A,20B,20C,20D,20E,20F,210,211,212,213}
行主要
{000,001,002,003,004,005,006,007,008,009,00A,00B,00C,00D,00E,00F,010011012013,100,101,102,103,104,105,106,107,108,109,10A,10B,10C,10D,10E,10F,110111112113,200,201,202,203,204,205,206,207,208,209,20A,20B,20C,20D,20E,20F,210211212213 }
column major {000,004,008,00C,010,001,005,009,00D,011,002,006,00A,00E,012,003,007,00B,00F,013, 100,104,108,10C,110,101,105,109,10D,111,102,106,10A,10E,112,103,107,10B,10F,113, 200,204,208,20C,210,201,205,209,20D,211,202,206,20A,20E,212,203,207,20B,20F,213}
柱主要{000,004,008,00C,010,001,005,009,00D,011,002,006,00A,00E,012,003,007,00B,00F,013,100,104,108,10C,110,101,105,109,10D,111,102,106,10A,10E,112,103,107,10B,10F,113,200,204,208,20C ,210,201,205,209,20D,211,202,206,20A,20E,212,203,207,20B,20F,213}
Calculation offset for arr[1][2][3] using row major offset? Calculation offset for arr[1][2][3] using column major offset?
采纳答案by mrwes
When I asked this question I was hoping to find some good 3 dimensional array examples. Especially code examples. Since I didn't find anything that was understandable, I decided to create a little C program to help display the concept. It uses the same test data in a 3x4x5 array. It also includes test data for a 5x5x5 array. It creates a column major array from the row major array so the offset calculations can be verified.
The array offset methods are:
当我问这个问题时,我希望能找到一些好的 3 维数组示例。尤其是代码示例。由于我没有找到任何可以理解的东西,我决定创建一个小 C 程序来帮助展示这个概念。它在 3x4x5 数组中使用相同的测试数据。它还包括 5x5x5 阵列的测试数据。它从行主数组创建一个列主数组,以便可以验证偏移量计算。
数组偏移方法是:
I added comments in the code where applicable to help clarify what the code is doing.
//
// Arrays.cpp :
// Purpose: Display rowMajor & colMajor data and calculations.
//
#include "stdafx.h"
#define _show_Arrays 1 // 1=display rowMajor & colMajor arrays
#define _square_array 0 // 1=use arr[5][5][5], 0=use arr[3][4][5]
#if (_square_array == 1)
const int depthSz = 5;
const int rowSz = 5;
const int colSz = 5;
/*
+---+---+---+---+---+
|x00|x01|x02|x03|x04|
+---+---+---+---+---+
|x05|x06|x07|x08|x09|
+---+---+---+---+---+
|x0A|x0B|x0C|x0D|x0E|
+---+---+---+---+---+
|x0F|x10|x11|x12|x13|
+---+---+---+---+---+
|x14|x15|x16|x17|x18|
+---+---+---+---+---+
slice x
*/
short row_arr[depthSz][colSz][rowSz] = {
{ /* slice 0 */
{0x000,0x001,0x002,0x003,0x004},
{0x005,0x006,0x007,0x008,0x009},
{0x00A,0x00B,0x00C,0x00D,0x00E},
{0x00F,0x010,0x011,0x012,0x013},
{0x014,0x015,0x016,0x017,0x018}},
{ /* slice 1 */
{0x100,0x101,0x102,0x103,0x104},
{0x105,0x106,0x107,0x108,0x109},
{0x10A,0x10B,0x10C,0x10D,0x10E},
{0x10F,0x110,0x111,0x112,0x113},
{0x114,0x115,0x116,0x117,0x118}},
{ /* slice 2 */
{0x200,0x201,0x202,0x203,0x204},
{0x205,0x206,0x207,0x208,0x209},
{0x20A,0x20B,0x20C,0x20D,0x20E},
{0x20F,0x210,0x211,0x212,0x213},
{0x214,0x215,0x216,0x217,0x218}},
{ /* slice 3 */
{0x300,0x301,0x302,0x303,0x304},
{0x305,0x306,0x307,0x308,0x309},
{0x30A,0x30B,0x30C,0x30D,0x30E},
{0x30F,0x310,0x311,0x312,0x313},
{0x314,0x315,0x316,0x317,0x318}},
{ /* slice 4 */
{0x400,0x401,0x402,0x403,0x404},
{0x405,0x406,0x407,0x408,0x409},
{0x40A,0x40B,0x40C,0x40D,0x40E},
{0x40F,0x410,0x411,0x412,0x413},
{0x414,0x415,0x416,0x417,0x418}}
};
#else
const int depthSz = 3;
const int rowSz = 4;
const int colSz = 5;
/*
+---+---+---+---+
|000|001|002|003|
+---+---+---+---+
|004|005|006|007|
+---+---+---+---+
|008|009|00A|00B|
+---+---+---+---+
|00C|00D|00E|00F|
+---+---+---+---+
|010|011|012|013|
+---+---+---+---+
slice x
*/
short row_arr[depthSz][colSz][rowSz] = {
{ /* slice 0 */
{0x000,0x001,0x002,0x003},
{0x004,0x005,0x006,0x007},
{0x008,0x009,0x00A,0x00B},
{0x00C,0x00D,0x00E,0x00F},
{0x010,0x011,0x012,0x013}},
{ /* slice 1 */
{0x100,0x101,0x102,0x103},
{0x104,0x105,0x106,0x107},
{0x108,0x109,0x10A,0x10B},
{0x10C,0x10D,0x10E,0x10F},
{0x110,0x111,0x112,0x113}},
{ /* slice 2 */
{0x200,0x201,0x202,0x203},
{0x204,0x205,0x206,0x207},
{0x208,0x209,0x20A,0x20B},
{0x20C,0x20D,0x20E,0x20F},
{0x210,0x211,0x212,0x213}}
};
#endif
short col_arr[depthSz*colSz*rowSz]; //
char *calc_RowMajor(char *Base, int elemSz, int depth_idx, int row_idx, int col_idx)
{ // row major slice is navigated by rows
char *address;
int lbound = 0; // lower bound (0 for zero-based arrays)
address = Base /* use base passed */
+ ((depth_idx-lbound)*(colSz*rowSz*elemSz)) /* select slice */
+ ((row_idx-lbound)*rowSz*elemSz) /* select row */
+ ((col_idx-lbound)*elemSz); /* select col */
return address;
}
char *calc_ColMajor(char *Base, int elemSz, int depth_idx, int col_idx, int row_idx)
{ // col major slice is navigated by columns
char *address;
int lbound = 0; // lower bound (0 for zero-based arrays)
int pageSz = colSz*rowSz*elemSz;
int offset;
offset = (col_idx-lbound)*(colSz*elemSz) /* select column */
+ (row_idx-lbound)*(elemSz); /* select row */
if (offset >= pageSz)
{ // page overflow, rollover
offset -= (pageSz-elemSz); /* ajdust offset back onto page */
}
address = Base /* use base passed */
+ ((depth_idx-lbound)*pageSz) /* select slice */
+ offset;
return address;
}
void disp_slice(char *pStr, short *pArr,int slice,int cols, int rows)
{
printf("== %s slice %d == %p\r\n",pStr, slice,pArr+(slice*rows*cols));
for(int x=0;x<rows;x++)
{
for(int y=0;y<cols;y++)
printf("%03X ",*(pArr+(slice*rows*cols)+(x*cols)+y));
printf("\r\n");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
// initialize col based array using row based array data
{ // convert row_arr into col_arr
short *pSrc = &row_arr[0][0][0];
short *pDst = &col_arr[0];
for(int d=0;d<depthSz;d++)
for(int r=0;r<rowSz;r++)
for(int c=0;c<colSz;c++)
{
*pDst++ = *(pSrc+((d*rowSz*colSz)+(c*rowSz)+r));
}
}
printf("Using Array[%d][%d][%d]\r\n",depthSz,rowSz,colSz);
#if (_show_Arrays == 1)
{ for(int x=0;x<depthSz;x++) {disp_slice("rowMajor",&row_arr[0][0][0],x,rowSz,colSz);}}
{ for(int x=0;x<depthSz;x++) {disp_slice("colMajor",&col_arr[0],x,rowSz,colSz);}}
#endif
int d = 2; // depth
int r = 3; // row
int c = 4; // column
for(d=0;d<depthSz;d++)
{
c = r = d; // simple access test pattern arr[0][0][0],arr[1][1][1],arr[2][2][2],...
{ // retrieve Array element
printf(" row_arr[%d][%d][%d] = %x\t",d,r,c,row_arr[d][r][c]);
printf("&row_arr[%d][%d][%d] = %p\r\n",d,r,c,&row_arr[d][r][c]);
}
{ // retrieve RowMajor element
short *pRowMajor = (short*)calc_RowMajor((char*)&row_arr[0][0][0],sizeof(short),d,r,c);
printf("calc_RowMajor(%d,%d,%d) = %x\t\t",d,r,c,*pRowMajor);
printf("pRowMajor = %p\r\n",pRowMajor);
}
{ // retrieve ColMajor element
short *pColMajor = (short*)calc_ColMajor((char*)&col_arr[0],sizeof(short),d,c,r);
printf("calc_ColMajor(%d,%d,%d) = %x\t\t",d,r,c,*pColMajor);
printf("pColMajor = %p\r\n",pColMajor);
}
} // for
getchar(); // just to hold the console while looking at the information
return 0;
}
我在代码中添加了适用的注释以帮助阐明代码在做什么。
//
// Arrays.cpp :
// Purpose: Display rowMajor & colMajor data and calculations.
//
#include "stdafx.h"
#define _show_Arrays 1 // 1=display rowMajor & colMajor arrays
#define _square_array 0 // 1=use arr[5][5][5], 0=use arr[3][4][5]
#if (_square_array == 1)
const int depthSz = 5;
const int rowSz = 5;
const int colSz = 5;
/*
+---+---+---+---+---+
|x00|x01|x02|x03|x04|
+---+---+---+---+---+
|x05|x06|x07|x08|x09|
+---+---+---+---+---+
|x0A|x0B|x0C|x0D|x0E|
+---+---+---+---+---+
|x0F|x10|x11|x12|x13|
+---+---+---+---+---+
|x14|x15|x16|x17|x18|
+---+---+---+---+---+
slice x
*/
short row_arr[depthSz][colSz][rowSz] = {
{ /* slice 0 */
{0x000,0x001,0x002,0x003,0x004},
{0x005,0x006,0x007,0x008,0x009},
{0x00A,0x00B,0x00C,0x00D,0x00E},
{0x00F,0x010,0x011,0x012,0x013},
{0x014,0x015,0x016,0x017,0x018}},
{ /* slice 1 */
{0x100,0x101,0x102,0x103,0x104},
{0x105,0x106,0x107,0x108,0x109},
{0x10A,0x10B,0x10C,0x10D,0x10E},
{0x10F,0x110,0x111,0x112,0x113},
{0x114,0x115,0x116,0x117,0x118}},
{ /* slice 2 */
{0x200,0x201,0x202,0x203,0x204},
{0x205,0x206,0x207,0x208,0x209},
{0x20A,0x20B,0x20C,0x20D,0x20E},
{0x20F,0x210,0x211,0x212,0x213},
{0x214,0x215,0x216,0x217,0x218}},
{ /* slice 3 */
{0x300,0x301,0x302,0x303,0x304},
{0x305,0x306,0x307,0x308,0x309},
{0x30A,0x30B,0x30C,0x30D,0x30E},
{0x30F,0x310,0x311,0x312,0x313},
{0x314,0x315,0x316,0x317,0x318}},
{ /* slice 4 */
{0x400,0x401,0x402,0x403,0x404},
{0x405,0x406,0x407,0x408,0x409},
{0x40A,0x40B,0x40C,0x40D,0x40E},
{0x40F,0x410,0x411,0x412,0x413},
{0x414,0x415,0x416,0x417,0x418}}
};
#else
const int depthSz = 3;
const int rowSz = 4;
const int colSz = 5;
/*
+---+---+---+---+
|000|001|002|003|
+---+---+---+---+
|004|005|006|007|
+---+---+---+---+
|008|009|00A|00B|
+---+---+---+---+
|00C|00D|00E|00F|
+---+---+---+---+
|010|011|012|013|
+---+---+---+---+
slice x
*/
short row_arr[depthSz][colSz][rowSz] = {
{ /* slice 0 */
{0x000,0x001,0x002,0x003},
{0x004,0x005,0x006,0x007},
{0x008,0x009,0x00A,0x00B},
{0x00C,0x00D,0x00E,0x00F},
{0x010,0x011,0x012,0x013}},
{ /* slice 1 */
{0x100,0x101,0x102,0x103},
{0x104,0x105,0x106,0x107},
{0x108,0x109,0x10A,0x10B},
{0x10C,0x10D,0x10E,0x10F},
{0x110,0x111,0x112,0x113}},
{ /* slice 2 */
{0x200,0x201,0x202,0x203},
{0x204,0x205,0x206,0x207},
{0x208,0x209,0x20A,0x20B},
{0x20C,0x20D,0x20E,0x20F},
{0x210,0x211,0x212,0x213}}
};
#endif
short col_arr[depthSz*colSz*rowSz]; //
char *calc_RowMajor(char *Base, int elemSz, int depth_idx, int row_idx, int col_idx)
{ // row major slice is navigated by rows
char *address;
int lbound = 0; // lower bound (0 for zero-based arrays)
address = Base /* use base passed */
+ ((depth_idx-lbound)*(colSz*rowSz*elemSz)) /* select slice */
+ ((row_idx-lbound)*rowSz*elemSz) /* select row */
+ ((col_idx-lbound)*elemSz); /* select col */
return address;
}
char *calc_ColMajor(char *Base, int elemSz, int depth_idx, int col_idx, int row_idx)
{ // col major slice is navigated by columns
char *address;
int lbound = 0; // lower bound (0 for zero-based arrays)
int pageSz = colSz*rowSz*elemSz;
int offset;
offset = (col_idx-lbound)*(colSz*elemSz) /* select column */
+ (row_idx-lbound)*(elemSz); /* select row */
if (offset >= pageSz)
{ // page overflow, rollover
offset -= (pageSz-elemSz); /* ajdust offset back onto page */
}
address = Base /* use base passed */
+ ((depth_idx-lbound)*pageSz) /* select slice */
+ offset;
return address;
}
void disp_slice(char *pStr, short *pArr,int slice,int cols, int rows)
{
printf("== %s slice %d == %p\r\n",pStr, slice,pArr+(slice*rows*cols));
for(int x=0;x<rows;x++)
{
for(int y=0;y<cols;y++)
printf("%03X ",*(pArr+(slice*rows*cols)+(x*cols)+y));
printf("\r\n");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
// initialize col based array using row based array data
{ // convert row_arr into col_arr
short *pSrc = &row_arr[0][0][0];
short *pDst = &col_arr[0];
for(int d=0;d<depthSz;d++)
for(int r=0;r<rowSz;r++)
for(int c=0;c<colSz;c++)
{
*pDst++ = *(pSrc+((d*rowSz*colSz)+(c*rowSz)+r));
}
}
printf("Using Array[%d][%d][%d]\r\n",depthSz,rowSz,colSz);
#if (_show_Arrays == 1)
{ for(int x=0;x<depthSz;x++) {disp_slice("rowMajor",&row_arr[0][0][0],x,rowSz,colSz);}}
{ for(int x=0;x<depthSz;x++) {disp_slice("colMajor",&col_arr[0],x,rowSz,colSz);}}
#endif
int d = 2; // depth
int r = 3; // row
int c = 4; // column
for(d=0;d<depthSz;d++)
{
c = r = d; // simple access test pattern arr[0][0][0],arr[1][1][1],arr[2][2][2],...
{ // retrieve Array element
printf(" row_arr[%d][%d][%d] = %x\t",d,r,c,row_arr[d][r][c]);
printf("&row_arr[%d][%d][%d] = %p\r\n",d,r,c,&row_arr[d][r][c]);
}
{ // retrieve RowMajor element
short *pRowMajor = (short*)calc_RowMajor((char*)&row_arr[0][0][0],sizeof(short),d,r,c);
printf("calc_RowMajor(%d,%d,%d) = %x\t\t",d,r,c,*pRowMajor);
printf("pRowMajor = %p\r\n",pRowMajor);
}
{ // retrieve ColMajor element
short *pColMajor = (short*)calc_ColMajor((char*)&col_arr[0],sizeof(short),d,c,r);
printf("calc_ColMajor(%d,%d,%d) = %x\t\t",d,r,c,*pColMajor);
printf("pColMajor = %p\r\n",pColMajor);
}
} // for
getchar(); // just to hold the console while looking at the information
return 0;
}
回答by Cory Walker
I would see the Row-major orderWikipedia article. There is a section that described dimensions higher than 2. There is also a good article here. That article gives the following formula for a three-dimensional array using a row-major layout:
我会看到Row-major orderWikipedia 文章。目前所描述的尺寸高于2节也有一个很好的文章在这里。那篇文章给出了使用行优先布局的三维数组的以下公式:
Address = Base + ((depthindex*col_size+colindex) * row_size + rowindex) * Element_Size
For a 3D array: type A[depth][col][row]. The base is the starting offset of the array. In addition, the size variables are the different sizes of each dimension. The Element_Size variable denotes the size of whatever type the array is composed of.
对于 3D 数组:键入 A[depth][col][row]。基数是数组的起始偏移量。另外,大小变量是每个维度的不同大小。Element_Size 变量表示组成数组的任何类型的大小。
Suppose you had row-major array a[4][6][5] composed of standard C++ integers. To compute the offset of a[1][3][2], you would plug the following numbers into the formula:
假设您有一个由标准 C++ 整数组成的行主数组 a[4][6][5]。要计算 a[1][3][2] 的偏移量,您需要将以下数字代入公式:
Address = Base + ((1 * 6 + 3) * 5 + 2) * 4
For a 3 dimensional array that has a column-major layout, the equation would rather be this:
对于具有列优先布局的 3 维数组,方程更像是这样:
Address = Base + ((rowindex*col_size+colindex) * depth_size + depthindex) * Element_Size
The numbers you would plug in for the example above using a column-major layout would now be this:
您将使用列主要布局为上面的示例插入的数字现在是这样的:
Address = Base + ((2 * 6 + 3) * 4 + 1) * 4
回答by Trevor Boyd Smith
Don't artificially constrain yourself by focusing on 3-dimensional and 2-dimensional. Instead focus on learning the expression for addressing n-dimensional arrays.
不要通过关注 3 维和 2 维人为地约束自己。而是专注于学习寻址 n 维数组的表达式。
Expressing n-dimensional addressing would solidfy your grasp on this subject and will be easier to remember one formula rather than separate formulas for 2d and 3d addressing.
表达 n 维寻址将巩固您对这一主题的掌握,并且将更容易记住一个公式,而不是 2d 和 3d 寻址的单独公式。
Here's my attempt at n-dimensional addressing:
这是我对 n 维寻址的尝试:
#define LEN 10
int getValue_nDimensions( int * baseAddress, int * indexes, int nDimensions ) {
int i;
int offset = 0;
for( i = 0; i < nDimensions; i++ ) {
offset += pow(LEN,i) * indexes[nDimensions - (i + 1)];
}
return *(baseAddress + offset);
}
int main() {
int i;
int * baseAddress;
int val1;
int val2;
// 1 dimensions
int array1d[LEN];
int array1d_indexes[] = {2};
int array1d_nDimensions = 1;
baseAddress = &array1d[0];
for(i = 0; i < LEN; i++) { baseAddress[i] = i; }
val1 = array1d[2];
val2 = getValue_nDimensions( // Equivalent to: val1 = array1d[2];
baseAddress,
&array1d_indexes[0],
array1d_nDimensions
);
printf("SANITY CHECK: %d %d\n",val1,val2);
// 3 dimensions
int array3d[LEN][LEN][LEN];
int array3d_indexes[] = {2,3,4};
int array3d_nDimensions = 3;
baseAddress = &array3d[0][0][0];
for(i = 0; i < LEN*LEN*LEN; i++) { baseAddress[i] = i; }
val1 = array3d[2][3][4];
val2 = getValue_nDimensions( // Equivalent to: val1 = array3d[2][3][4];
baseAddress,
&array3d_indexes[0],
array3d_nDimensions
);
printf("SANITY CHECK: %d %d\n",val1,val2);
// 5 dimensions
int array5d[LEN][LEN][LEN][LEN][LEN];
int array5d_indexes[] = {2,3,4,5,6};
int array5d_nDimensions = 5;
baseAddress = &array5d[0][0][0][0][0];
for(i = 0; i < LEN*LEN*LEN*LEN*LEN; i++) { baseAddress[i] = i; }
val1 = array5d[2][3][4][5][6];
val2 = getValue_nDimensions( // Equivalent to: val1 = array5d[2][3][4][5][6];
baseAddress,
&array5d_indexes[0],
array5d_nDimensions
);
printf("SANITY CHECK: %d %d\n",val1,val2);
return 0;
}
Output:
输出:
SANITY CHECK: 2 2
SANITY CHECK: 234 234
SANITY CHECK: 23456 23456
回答by ojblass
The terms 'row major' and 'column major' don't translate well to a third dimention. The notion that the next element stored is from the current row or current column break down. It sounds a little comical but this becomes 'depth major' vs. 'width major' ordering. Each subsequent element is no longer a single entry but one full two dimentional matrix.
术语“行专业”和“列专业”不能很好地转换为第三个维度。存储的下一个元素来自当前行或当前列的概念被打破了。这听起来有点滑稽,但这变成了“深度专业”与“宽度专业”的排序。每个后续元素不再是单个条目,而是一个完整的二维矩阵。
/ X / +---+---+---+ / / / /| +---+---+---+-+------- | 1 | 5 | 9 |/| Y +---+---+---+ + | 2 | 6 | A |/| +---+---+---+ + | 3 | 7 | B |/| +---+---+---+ + | 4 | 8 | C |/ +---+---+---+
So the memory would literally have 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 in memory sequentially. This is classical column major ordering. By placing the D entry at the position marked X you have not changed the fact that your matrix has colum major ordering. If you place the D entry where the Y is you still have not changed the fact that you are using column major ordering. Where you decide to place the next block will affect if you are using depth major (X) or width major (Y) ordering. As you well know these are equivalents but calling it something may assist you writing equations:
因此,内存将按顺序在内存中具有 1、2、3、4、5、6、7、8、9、10、11、12、13。这是经典的列主要排序。通过将 D 条目放置在标记为 X 的位置,您并没有改变矩阵具有主要排序的事实。如果您将 D 条目放在 Y 所在的位置,您仍然没有改变您使用列主要排序的事实。您决定放置下一个块的位置将影响您是使用深度主要 (X) 还是宽度主要 (Y) 排序。众所周知,这些是等价的,但称其为某些东西可能有助于您编写方程式:
[ 0 Based arrays assumed ]
[假设 0 基于数组]
You access the memory location of a two dimentional colum major element through the equation:
您可以通过以下等式访问二维列主元素的内存位置:
MatrixOffset = base + (sizeof(entry) * ((4 * ( column - 1 )) + (row - 1)))
This address would be adjusted using depth or width its all a matter of terminology.
该地址将使用深度或宽度进行调整,这完全是术语问题。
TotalOffset = MatrixOffset + (sizeof(entry) * ((4 * 3) * (depth - 1)))
OR
或者
TotalOffset = MatrixOffset + (sizeof(entry) * ((4 * 3) * (width - 1)))
The constants 4 and 3 would likely be variables COLUMNS and ROWS.
常量 4 和 3 可能是变量 COLUMNS 和 ROWS。
Don't ask me about the 4th dimention!
不要问我关于第四维的问题!
回答by ojblass
Basically in a 3D arrray with row major E.g Arr[3][4][5] when u want Arr[0],it looks for the front slice of the image like above Arr[1] second slice and so on. so Arr[0] means 2D array of size [4][5] ,so every Arr[x] corresponds to x*(4*5) Now about Arr[x][y] can be thought of a 1D array of size [5] whose position is [x][y] from top view in the image above so when when we want Arr[x][y] = x*(4*5)+y*(5) now Arr[x][y][z] is the specific element of Arr[x][y] at depth z Arr[x][y][z]=x*(4*5)+y*5+z now on the basis of size of the data type u want to store in the array,the offset can be multiplied to the size get the address with respect to start
基本上在具有行主要的 3D 数组中,例如 Arr[3][4][5],当您想要 Arr[0] 时,它会查找图像的前切片,如上面的 Arr[1] 第二个切片,依此类推。所以 Arr[0] 表示大小为 [4][5] 的二维数组,所以每个 Arr[x] 对应于 x*(4*5) 现在关于 Arr[x][y] 可以认为是一个大小的一维数组[5] 从上图中的顶视图看,其位置是 [x][y] 所以当我们想要 Arr[x][y] = x*(4*5)+y*(5) 现在时 Arr[x] [y][z] 是 Arr[x][y] 在深度 z 的特定元素 Arr[x][y][z]=x*(4*5)+y*5+z 现在基于你想存储在数组中的数据类型的大小,偏移量可以乘以大小得到相对于开始的地址
回答by trijezdci
The formula for k-dimensional arrays is
k维数组的公式是
k-1 n
i + ∑ i * ∏ c
0 n=1 n m=0 m
where i subscript n is the index of dimension n for n = { 0, 1, 2, ... k-1 } and c subscript m is the cardinality of dimension m for m = { 0, 1, 2, ... k-2 }.
其中 i 下标 n 是 n = { 0, 1, 2, ... k-1 } 的维度 n 的索引, c 下标 m 是 m = { 0, 1, 2, ... 的维度 m 的基数k-2 }。
A nicer rendering of the formula in PNG format can be found here:
可以在此处找到 PNG 格式的公式的更好渲染:
http://modula-2.info/m2r10/pmwiki.php/Spec/LanguageReport#MultiDimensionalArrays
http://modula-2.info/m2r10/pmwiki.php/Spec/LanguageReport#MultiDimensionalArrays