代码改变世界

C语言 数组 列优先 实现

2013-11-02 23:04  wid  阅读(2932)  评论(0编辑  收藏  举报

C语言数组结构列优先顺序存储的实现 (GCC编译)。

从行优先转换为列优先存储方式, 与行优先相比, 不同之处在于改变了数组维界基址的先后顺序, 从而改变了映像函数常量基址。

  1 /**
  2 * @brief C语言 数组 列优先 实现
  3 * @author wid
  4 * @date 2013-11-02
  5 *
  6 * @note 若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢!
  7 */
  8 
  9 #include <stdio.h>
 10 #include <stdlib.h>
 11 #include <stdarg.h>
 12 #include <assert.h>
 13 
 14 #define OK 1
 15 #define ERROR -1
 16 
 17 #define MAX_DIM 8       ///允许的最大数组维数
 18 
 19 typedef int ElemType;
 20 
 21 typedef struct
 22 {
 23     ElemType *base;         ///数组元素基址
 24     int dim;                ///数组维数
 25     int *bounds;            ///数组维界基址
 26     int *constants;         ///数组映像函数常量基址
 27 }Array;     ///数组结构
 28 
 29 ///数组方法声明
 30 int InitArray( Array *pArr, int nDim, ... );        ///初始化数组 pArr
 31 void DestroyArray( Array *pArr );                   ///销毁数组 pArr
 32 int Locate( Array *pArr, int nDim, va_list ap );                     ///定位下标指向的元素在数组中的位置
 33 int Assign( Array *pArr, ElemType *elm, ... );      ///数组赋值
 34 int Value( Array *pArr, ElemType *elm, ... );       ///数组取值
 35 
 36 ///数组方法实现
 37 
 38 /**
 39 * @brief 初始化数组
 40 *
 41 * @param pArr 指向待初始化的数组
 42 * @param nDim 数组的维数
 43 * @param ... 数组各维数的长度
 44 *
 45 * @return 初始化成功返回OK, 否则返回ERROR
 46 */
 47 int InitArray( Array *pArr, int nDim, ... )
 48 {
 49     if( nDim < 1 || nDim > MAX_DIM )
 50         return ERROR;
 51 
 52     ///初始化 pArr 数组维数属性
 53     pArr->dim = nDim;
 54 
 55     ///构造数组维界基址
 56     pArr->bounds = (int *)malloc( nDim * sizeof(int) );
 57     if( !pArr->bounds )
 58         return ERROR;
 59 
 60     int i = 0, nElemCount = 1;
 61     va_list ap;
 62     va_start( ap, nDim );
 63 
 64     /// i = nDim - 1, 使列优先
 65     for( i = nDim - 1; i >= 0; --i )
 66     {
 67         pArr->bounds[i] = va_arg( ap, int );
 68         if( pArr->bounds[i] < 0 )
 69             return ERROR;
 70 
 71         nElemCount *= pArr->bounds[i];
 72     }
 73     va_end(ap);
 74 
 75     ///初始化元素基址
 76     pArr->base = (ElemType *)malloc( nElemCount * sizeof(ElemType) );
 77     if( !pArr->base )
 78         return ERROR;
 79 
 80     ///初始化函数映像常数基址
 81     pArr->constants = (int *)malloc( nDim * sizeof(int) );
 82 
 83     ///递推求常量基址, 列优先
 84     pArr->constants[nDim-1] = 1;
 85     for( i = nDim -2 ; i >= 0; --i )
 86     {
 87         pArr->constants[i] = pArr->bounds[i+1] * pArr->constants[i+1];
 88     }
 89 
 90     return OK;
 91 }
 92 
 93 /**
 94 * @brief 销毁数组 pArr
 95 *
 96 * @param pArr 指向待销毁的数组
 97 */
 98 void DestroyArray( Array *pArr )
 99 {
100     if( pArr->base )
101         free( pArr->base );
102 
103     if( pArr->bounds )
104         free( pArr->bounds );
105 
106     if( pArr->constants )
107         free( pArr->constants );
108 }
109 
110 /**
111 * @brief 定位数组下标指向的元素在数组中的位置
112 *
113 * @param 指向的数组
114 * @param ... 数组的下标
115 *
116 * @return 若下标合法, 返回下标在数组中的位置, 否则返回 ERROR
117 */
118 int Locate( Array *pArr, int nDim, va_list ap )
119 {
120     int nPos = 0, ind = 0, i = 0;
121 
122     ///列优先求地址
123     for( i = pArr->dim - 1; i >= 0; --i )
124     {
125         ind = va_arg( ap, int );
126 
127         ///使用断言, 确保下标合法
128         assert( ind >= 0 && ind < pArr->bounds[i] );
129 
130         nPos += pArr->constants[i] * ind;
131     }
132     va_end(ap);
133 
134     return nPos;
135 }
136 
137 /**
138 * @brief 数组赋值
139 *
140 * @param pArr 指向待赋值的数组
141 * @param elm 指向赋值元素
142 * @param nDim 数组维数
143 * @param ... 数组下标
144 *
145 * @param 赋值成功返回 OK, 否则返回 ERROR
146 */
147 int Assign( Array *pArr, ElemType *elm, ... )
148 {
149     int nPos = 0;
150     va_list ap;
151     va_start( ap, elm );
152     nPos = Locate( pArr, pArr->dim, ap );
153     *(pArr->base + nPos) = *elm;
154 
155     return OK;
156 }
157 
158 /**
159 * @brief 数组取值
160 
161 */
162 int Value( Array *pArr, ElemType *elm, ... )
163 {
164     int nPos = 0;
165     va_list ap;
166     va_start( ap, elm );
167     nPos = Locate( pArr, pArr->dim, ap );
168     *elm = *(pArr->base + nPos);
169     printf( "addr = 0x%X\n", pArr->base + nPos );
170 
171     return OK;
172 }
173 
174 int main()
175 {
176     Array arr;
177 
178     ///初始化一个三维数组, 大小为 2x3x5
179     InitArray( &arr, 3, 2, 3, 5 );
180 
181     int a = 0;
182     ///赋值测试
183     int i = 0, m = 0, n = 0;
184     for( i = 0; i < 2; ++i )
185         for( m = 0; m < 3; ++m )
186             for( n = 0; n < 5; ++n )
187             {
188                 a = i + m + n;
189                 Assign( &arr, &a, i, m, n );
190             }
191 
192     int b = 0;
193     ///取值测试
194     for( i = 0; i < 2; ++i )
195         for( m = 0; m < 3; ++m )
196             for( n = 0; n < 5; ++n )
197             {
198                  Value( &arr, &b, i, m, n );
199                  printf( "[%d][%d][%d]=%d\n", i, m, n, b );
200             }
201 
202     ///销毁数组
203     DestroyArray( &arr );
204 
205     return 0;
206 }

运行测试:

 

若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢。