如果我们按照C语言的方式存储它,也就是行优先存储的话,那么在内存中,它的形状是这样的:
这种存储方式又被称作C contiguous array。
C语言数组结构列优先顺序存储的实现 (GCC编译)。
从行优先转换为列优先存储方式,与行优先相比,不同之处在于改变了数组维界基址的先后顺序, 从而改变了映像函数常量基址。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
/**
* @brief C语言 数组 列优先 实现
* @author wid
* @date 2013-11-02
*
* @note 若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢!
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#define OK 1
#define ERROR -1
#define MAX_DIM 8 ///允许的最大数组维数
typedef int ElemType;
typedef struct
{
ElemType *base; ///数组元素基址
int dim; ///数组维数
int *bounds; ///数组维界基址
int *constants; ///数组映像函数常量基址
}Array; ///数组结构
///数组方法声明
int InitArray( Array *pArr, int nDim, ... ); ///初始化数组 pArr
void DestroyArray( Array *pArr ); ///销毁数组 pArr
int Locate( Array *pArr, int nDim, va_list ap ); ///定位下标指向的元素在数组中的位置
int Assign( Array *pArr, ElemType *elm, ... ); ///数组赋值
int Value( Array *pArr, ElemType *elm, ... ); ///数组取值
///数组方法实现
/**
* @brief 初始化数组
*
* @param pArr 指向待初始化的数组
* @param nDim 数组的维数
* @param ... 数组各维数的长度
*
* @return 初始化成功返回OK, 否则返回ERROR
*/
int InitArray( Array *pArr, int nDim, ... )
{
|| nDim > MAX_DIM )
return ERROR;
///初始化 pArr 数组维数属性
pArr->dim = nDim;
///构造数组维界基址
pArr->bounds = ( int *) malloc ( nDim * sizeof ( int ) );
if ( !pArr->bounds )
return ERROR;
, nElemCount = ;
va_list ap;
va_start ( ap, nDim );
/// i = nDim - 1, 使列优先
; i >= ; --i )
{
pArr->bounds[i] = va_arg ( ap, int );
)
return ERROR;
nElemCount *= pArr->bounds[i];
}
va_end (ap);
///初始化元素基址
pArr->base = (ElemType *) malloc ( nElemCount * sizeof (ElemType) );
if ( !pArr->base )
return ERROR;
///初始化函数映像常数基址
pArr->constants = ( int *) malloc ( nDim * sizeof ( int ) );
///递推求常量基址, 列优先
pArr->constants[nDim-] = ;
; i >= ; --i )
{
pArr->constants[i] = pArr->bounds[i+] * pArr->constants[i+];
}
return OK;
}
/**
* @brief 销毁数组 pArr
*
* @param pArr 指向待销毁的数组
*/
void DestroyArray( Array *pArr )
{
if ( pArr->base )
free ( pArr->base );
if ( pArr->bounds )
free ( pArr->bounds );
if ( pArr->constants )
free ( pArr->constants );
}
/**
* @brief 定位数组下标指向的元素在数组中的位置
*
* @param 指向的数组
* @param ... 数组的下标
*
* @return 若下标合法, 返回下标在数组中的位置, 否则返回 ERROR
*/
int Locate( Array *pArr, int nDim, va_list ap )
{
, ind = , i = ;
///列优先求地址
; i >= ; --i )
{
ind = va_arg ( ap, int );
///使用断言, 确保下标合法
assert ( ind >= && ind < pArr->bounds[i] );
nPos += pArr->constants[i] * ind;
}
va_end (ap);
return nPos;
}
/**
* @brief 数组赋值
*
* @param pArr 指向待赋值的数组
* @param elm 指向赋值元素
* @param nDim 数组维数
* @param ... 数组下标
*
* @param 赋值成功返回 OK, 否则返回 ERROR
*/
int Assign( Array *pArr, ElemType *elm, ... )
{
;
va_list ap;
va_start ( ap, elm );
nPos = Locate( pArr, pArr->dim, ap );
*(pArr->base + nPos) = *elm;
return OK;
}
/**
* @brief 数组取值
*/
int Value( Array *pArr, ElemType *elm, ... )
{
;
va_list ap;
va_start ( ap, elm );
nPos = Locate( pArr, pArr->dim, ap );
*elm = *(pArr->base + nPos);
printf ( "addr = 0x%X\n" , pArr->base + nPos );
return OK;
}
int main()
{
Array arr;
///初始化一个三维数组, 大小为 2x3x5
InitArray( &arr, , , , );
;
///赋值测试
, m = , n = ;
; i < ; ++i )
; m < ; ++m )
; n < ; ++n )
{
a = i + m + n;
Assign( &arr, &a, i, m, n );
}
;
///取值测试
; i < ; ++i )
; m < ; ++m )
; n < ; ++n )
{
Value( &arr, &b, i, m, n );
printf ( "[%d][%d][%d]=%d\n" , i, m, n, b );
}
///销毁数组
DestroyArray( &arr );
;
}
|
运行测试:
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对服务器之家的支持。
原文链接:https://www.3mooc.com/front/articleinfo/3669