主题:[原创]关于公共块变量排序问题
mltx
[专家分:20880] 发布于 2005-06-01 23:11:00
最近,好几个人问到公共块出错的问题,都是出于一个原因,特在这里把老贴整理一下供大家参考。
问题:
Compiling Fortran...
D:\FRAME2D.FOR
D:\FRAME2D.FOR(314) : Warning: Because of COMMON, the alignment of object is inconsistent with its type [ASA]
COMMON /EM/LM(6),ND,ASA(6,6),RF(6),SA(6,6)
--------------------------^
D:\FRAME2D.FOR(314) : Warning: Because of COMMON, the alignment of object is inconsistent with its type [RF]
COMMON /EM/LM(6),ND,ASA(6,6),RF(6),SA(6,6)
-----------------------------------^
解答:
这是老Fortran的规则。看你的公共语句:
COMMON /EM/LM(6),ND,ASA(6,6),RF(6),SA(6,6),SF(6),T(3,3)
根据程序的隐含规则,LM(6),ND一共是7个整型数,每个整型数4个字节,共28个字节,不是8字节的整倍数。紧跟着是双精度的ASA(6,6),每个数是8个字节,可是ASA(1,1)不能从8字节整倍数位置开始存储,这就是the alignment of object is inconsistent with its type 的意思。
对于警告错误,可以忽略,一般不致于影响执行结果。如果要改的话,有几种办法:
1)在公共语句中,把双精度数放在前边,整形数跟在后边;
2)在ASA()前插一个整型变量(哪怕是没用的),用来占用4个字节,以使得后面的双精度数可以从8字节整数倍位置开始存储。
准则:作为好的编程习惯,建议在公共块中,把实型变量排在前边,把整型数据放在后边,就不会有对位不整的错误!
仅供参考。
补充:(05.06.01)
公共块不是用堆栈实现的,是内存中的一段连续存储的数据。
按照Fortran的规定,当读取双精度数据时,总是假定前面的数据长度是双精度数字节长度(8个字节)的整数倍。
对于本例,ASA(1,1)从第29个字节开始存放8个字节;可是读取的时候,要从第33个字节(28不是8的倍数,32是28之后最小的8的倍数)开始读入8个字节,这就是定位(alignment)错误。
所以F90之后不提倡用公共块共享数据,而可用更为灵活的module来代替公共块共享数据。
公共块是过时的语言功能。
回复列表 (共28个回复)
11 楼
fisheagle [专家分:30] 发布于 2007-01-26 21:39:00
谢谢,又学到一招!
不好意思,以后我要多像大师LZ学习
12 楼
hliupeng [专家分:0] 发布于 2007-05-10 12:24:00
编程的时候确实没考虑这些。
那我想问一下,如果不用COMMON,而用MODULE来实现的话,对下面的问题怎么解决?
先后定义两组变量
COMMON F(NI,NJ,NK,NFMAX),P(NI,NJ,NK),RHO(NI,NJ,NK),GAM(NI,NJ,NK
COMMON U(NI,NJ,NK),V(NI,NJ,NK),W(NI,NJ,NK)
这两组变量享用相同的内存,不用COMMON的话怎么个定义法?
另外,用EQUIVALENCE语句定义的变量关系怎么在不用EQUIVALENCE的情况下来实现?
13 楼
mltx [专家分:20880] 发布于 2007-05-10 18:04:00
real,target :: F(NI,NJ,NK,NFMAX),P(NI,NJ,NK),RHO(NI,NJ,NK),GAM(NI,NJ,NK)
! 上一句可以放在一个模块里; 假设NFMAX>=3
real,pointer:: U(:,:,:),V(:,:,:),W(:,:,:)
U => F(:,:,:,1)
V => F(:,:,:,2)
W => F(:,:,:,3)
14 楼
hliupeng [专家分:0] 发布于 2007-05-11 14:33:00
学到了,谢谢!
15 楼
hliupeng [专家分:0] 发布于 2007-05-12 10:19:00
还有一个小问题再问一下还是关于指针
例如:common F(100,50,30,5)
common U(100,50,30),V(167),W(167)
像这种情况怎么用指针来搞定?
对于U()数组是很简单的,V和W呢? 我用如下的程序试了试,但是编译报错了
real,target::F(100,50,30,5)
real,pointer::U(:,:,:),V(:),W(:)
U=>F(:,:,:,1)
allocate(V(167))
V=>F(100,1,1,2)
allocate(W(167))
W=>F(68,2,1,2)
报错说指针的rank与目标的不一致.这种情况应该怎么来处理?
16 楼
mltx [专家分:20880] 发布于 2007-05-12 11:51:00
怎么会有这么怪的数据结构呢?若是我,一定设法躲避。
17 楼
hliupeng [专家分:0] 发布于 2007-05-12 13:53:00
呵呵,是啊,最好是不用这种数据结构,可我是在改人家的程序,没办法,很头疼.
不行的话只好在MODULE里面直接用原来的common语句了.
18 楼
mltx [专家分:20880] 发布于 2007-05-12 23:53:00
F90之后将Common列为要淘汰的特性,主要是针对新写的代码。
对原有的代码,若不做大的改动,Common可能比较难以轻易取代,这也是为什么标准还保留了这些语法特性。主要是为了和过去的代码兼容。
19 楼
hliupeng [专家分:0] 发布于 2007-05-16 13:10:00
mltx老师,还有一点小疑问
common F(NI,NJ,NK,NFMAX)
common DU(NI,NJ,NK),DV(NI,NJ,NK)
REAL,DIMENSION(NI,NJ,NK)::U,V
EQUIVALENCE(F(1,1,1,1),U(1,1,1)),(F(1,1,1,2),V(1,1,1))
假定NFMAX>=3
那么数组 DV和V是不是共享相同的内存的?
20 楼
hliupeng [专家分:0] 发布于 2007-05-16 13:13:00
mltx老师,还有一个小问题
COMMON F(NI,NJ,NK,NFMAX)
COMMON DU(NI,NJ,NK),DV(NI,NJ,NK)
REAL,DIMENSION(NI,NJ,NK)::U,V
EQUIVALENCE(F(1,1,1,1),U(1,1,1)),(F(1,1,1,2),V(1,1,1))
假定NFMAX>=3
那么,数组DV和V是不是共享相同的内存的?
我来回复