C++ 多维数组中的数组偏移量计算(主列与主行)
我最近读的一本教科书讨论了行主数组和列主数组。这本书主要关注一维和二维数组,但没有真正讨论三维数组。我正在寻找一些好的例子来帮助巩固我对使用行主数组和列主数组在多维数组中寻址元素的理解 +--+--+--+ | / / / /| | +--+--+--+ + | +---+---+---+---+ / / / /|/| | / / / / /| +--+--+--+ + + | +---+---+---+---+ + / / / /|/|/| | / / / / /|/| +--+--+--+ + + + | +---+---+---+---+ + + / / / /|/|/|/| | / / / / /|/|/| +--+--+--+ + + + + | +---+---+---+---+ + + + / / / /|/|/|/|/ | |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] +--+--+--+ | / / / /| | +--+--+--+ + | +---+---+---+---+ / / / /|/| | / / / / /| +--+--+--+ + + | +---+---+---+---+ + / / / /|/|/| | / / / / /|/| +--+--+--+ + + + | +---+---+---+---+ + + / / / /|/|/|/| | / / / / /|/|/| +--+--+--+ + + + + | +---+---+---+---+ + + + / / / /|/|/|/|/ | |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] 注:原始问题错误地表示为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 十六进制数据示例 +---+---+---+---+ +---+---+---+---+ +---+---+---+---+ |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 | +---+---+---+---+ +---+---+---+---+ +---+---+---+---+ |00C | 00D | 00E | 00F | 10C | 10D | 10E | 10F | 20C | 20D | 20E | 20F| +---+---+---+---+ +---+---+---+---+ +---+---+---+---+ |010|011|012|013| |110|111|112|113| |210|211|212|213| +---+---+---+---+ +---+---+---+---+ +---+---+---+---+ 切片0切片1切片2 短Arr[3][4][5];//假设数组中填充了十六进制测试数据 arr[1][2][3]=0x10B使用片1第2行第3列 arr[2][3][4]=0x210使用片2第3行第4列 解析为第4行第0列 行主修C++ 多维数组中的数组偏移量计算(主列与主行),c++,c,arrays,C++,C,Arrays,我最近读的一本教科书讨论了行主数组和列主数组。这本书主要关注一维和二维数组,但没有真正讨论三维数组。我正在寻找一些好的例子来帮助巩固我对使用行主数组和列主数组在多维数组中寻址元素的理解 +--+--+--+ | / / / /| | +--+--+--+ + | +---+---+---+---+ / / / /|/| | / / / / /| +--+--+--+
{000001002003004005006007008009,00A,00B,00C,00D,00E,00F,010011012013, 100101102103104105106107108109,10A,10B,10C,10D,10E,10F,110111112113, 200201202203204205205206207208209,20A、20B、20C、20D、20E、20F、210211212213} 主修专栏 {000004008,00C,010001005009,00D,011002006,00A,00E,012003007,00B,00F,013, 100104108,10C、110101105109,10D、111102106,10A、10E、112103107,10B、10F、113、, 200204208,20C、210201205209,20D、211202206,20A、20E、212203207,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? 使用行主偏移量计算arr[1][2][3]的偏移量? 使用列主偏移量计算arr[1][2][3]的偏移量? 我会看维基百科的文章。有一节描述了大于2的尺寸。还有一篇好文章。该文章给出了使用行主布局的三维数组的以下公式:
Address = Base + ((depthindex*col_size+colindex) * row_size + rowindex) * Element_Size
对于三维阵列:键入[depth][col][row]。基准是阵列的起始偏移量。此外,大小变量是每个维度的不同大小。Element_Size变量表示数组组成的任何类型的大小
假设你有行主数组A [4 ] [6 ] [5 ]由标准C++整数组成。要计算a[1][3][2]的偏移量,请将以下数字插入公式中:
Address = Base + ((1 * 6 + 3) * 5 + 2) * 4
对于具有列主布局的三维阵列,方程式应为:
Address = Base + ((rowindex*col_size+colindex) * depth_size + depthindex) * Element_Size
现在,您可以使用列主布局为上面的示例插入以下数字:
Address = Base + ((2 * 6 + 3) * 4 + 1) * 4
术语“行主视图”和“列主视图”不能很好地转换为第三维度。存储的下一个元素来自当前行或当前列分解的概念。听起来有点滑稽,但这变成了“深度主修”与“宽度主修”的排序。每个后续元素不再是单个条目,而是一个完整的二维矩阵 / X / +---+---+---+ / / / /| +---+---+---+-+------- | 1 | 5 | 9 |/| Y +---+---+---+ + | 2 | 6 | A |/| +---+---+---+ + | 3 | 7 | B |/| +---+---+---+ + | 4 | 8 | C |/ +---+---+---+ 该地址将使用深度或宽度进行调整,这完全是一个术语问题
TotalOffset = MatrixOffset + (sizeof(entry) * ((4 * 3) * (depth - 1)))
或
TotalOffset = MatrixOffset + (sizeof(entry) * ((4 * 3) * (width - 1)))
常量4和3可能是变量列和行
别问我关于第四维的事 基本上是在具有行主调的3D arrray中,例如Arr[3][4][5] 当您需要Arr[0]时,它会像上面那样查找图像的前片 Arr[1]第二个切片,依此类推。 因此,Arr[0]表示大小为[4][5]的2D数组,因此每个Arr[x]对应于x*(4*5) 现在,可以将Arr[x][y]看作是一个尺寸为[5]的一维数组,其位置在上图中俯视图的[x][y]处 所以当我们想要Arr[x][y]=x*(4*5)+y*(5) 现在Arr[x][y][z]是深度z处Arr[x][y]的特定元素 Arr[x][y][z]=x*(4*5)+y*5+z
现在,根据要存储在数组中的数据类型的大小,偏移量可以乘以大小以获得关于开始的地址。当我问这个问题时,我希望找到一些好的三维数组示例。特别是代码示例。因为我没有发现任何可以理解的东西,所以我决定创建一个小小的C程序来帮助展示这个概念。它在3x4x5阵列中使用相同的测试数据。它还包括5x5x5阵列的测试数据。它从行主数组创建列主数组,以便验证偏移计算。
阵列偏移方法包括:
我在代码中添加了注释(如果适用),以帮助澄清c
TotalOffset = MatrixOffset + (sizeof(entry) * ((4 * 3) * (width - 1)))
//
// 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;
}
#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;
}
SANITY CHECK: 2 2
SANITY CHECK: 234 234
SANITY CHECK: 23456 23456
k-1 n
i + ∑ i * ∏ c
0 n=1 n m=0 m