关于Fortran和C数组的优先模式
熟悉了C语言和Python中的行优先模式,上手Fortran的列优先模式时候有点绕,大致在这整理下思路。
无论对于C或者Fortran数据对象在内存中都是连续排列的。比如我初始化一个3×3的二维数组.
C语言1
2
3
4
5int c[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Fortran1
2
3integer :: f(3, 3)
integer :: r, c
data ((m(r, c), r=1, 3), c=1, 3) /(i, i=1,9)/ ! 注意我这里是按照列进行初始化的
通过上面两种语言的初始化数组的方式,数据对象在内存中存放的方式都是1|2|3|4|5|6|7|8|9
但是C和fortran对连续内存块进行随机存取时候的索引优先是不同的,C是按照行优先,也就是stride等于1,上述数据对象的分别为:1
c[0][0], c[0][1], c[0][2], c[1][0], c[1][1], c[1][2], c[2][0], c[2][1], c[2][2]
Fortran是列优先, stride等于3,上述对象分别为:1
f(1, 1), f(2, 1), f(3, 1), f(1, 2), f(2, 2), f(3, 2), f(1, 3), f(2, 3), f(3, 3)
对于经常使用的话,我觉得直接按照线性代数里面最直观的列向量来处理就行,估计Fortran在设计的时候也是科学家们方便操作列向量才这么设计的。
Fortran数组输出时的注意,write(*, *)
f进行输出时,是直接按照内存顺序输出的,也就是一列一列输出,但是看起来是一行一行的。
例如,
1 | program ex0714 |
输出就为
1 | 2 3 3 3 3 |
和我本意不同,所以要按照我的顺序输出就应该改一下输出顺序
1 | write(*, "(5(5I5, /))") ((m(i, j), j=1, size), i=1, size) |
输出:1
2
3
4
52 1 1 1 1
3 2 1 1 1
3 3 2 1 1
3 3 3 2 1
3 3 3 3 2
以上