首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

定位您的应用程序 - 小端和大端 IBM XL Fortran 编译器的差异对您意味着什么(3)

定位您的应用程序 - 小端和大端 IBM XL Fortran 编译器的差异对您意味着什么(3)

不同大小的项目之间的存储关联在将程序从大端移植到小端时,必须考虑不同大小的项目之间的存储关联。在 Fortran 中, 这涉及到 EQUIVALENCE、公共块、ENTRY 语句、参数关联,以及格式控制的 I/O。以下各小节将会更详细地介绍这些项目。
请注意,十六进制值始终按大端顺序进行打印。
EQUIVALENCEFortran 标准用 EQUIVALENCE 语句限制可以与存储关联在一起的对象的类型。但是,XL Fortran(和大多数编译器)允许几乎任何类型的对象出现在 EQUIVALENCE 中。当对不同大小的项目使用 EQUIVALENCE 时,小端和大端平台上的结果可能会有所不同。为了证明这一点,请考虑下面的程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
       integer(8) j
       integer(4) i(2)
       integer(2) h(4)
       integer(1) k(8)
       equivalence (j, i), (j, h), (j, k)
       j = z'0001020304050607'
       print 1, 'j = ', j
       print 2, 'i = ', i
       print 4, 'h = ', h
       print 8, 'k = ', k
1      format(A, "z'", z16.16, "'")
2      format(A, 2("z'", z8.8, "'", 1x))
4      format(A, 4("z'", z4.4, "'", 1x))
8      format(A, 8("z'", z2.2, "'", 1x))
       end




在上述程序中,我们指定 j 与 i、h 和 k 共享存储空间,它们的种类各不相同。在大端和小端中,数组都是从左到右排列的,更准确地说,最低的数组元素具有最低的内存地址。每个数组元素的字节顺序在大端和小端上都是不一样的。在大端上,每个数组元素中最大的字节都位于左侧,所以 j、i、h 和 k 在内存中看起来是一样的。输出是:
1
2
3
4
j = z'0001020304050607'
i = z'00010203' z'04050607'
h = z'0001' z'0203' z'0405' z'0607'
k = z'00' z'01' z'02' z'03' z'04' z'05' z'06' z'07'




在小端平台上,每个数组元素中最小的字节都位于左侧,所以 j、i、h 和 k 在内存中看起来是不一样的。输出是:
1
2
3
4
j = z'0001020304050607'
i = z'04050607' z'00010203'
h = z'0607' z'0405' z'0203' z'0001'
k = z'07' z'06' z'05' z'04' z'03' z'02' z'01' z'00'




公共块公共块提供了不同编译单元中的项目之间的存储关联。如果相同的公共块在两个编译单元中的声明不同,那么公共块成员是存储关联的。如果相应的成员具有不同的大小,当代码从大端移植到小端时需要有额外的考虑事项。请考虑下面的程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
       subroutine sub1
         integer(8) j
         common /blk/ j
         j = z'0001020304050607'
         print 1, 'sub1:', j
1        format(A, "z'", z16.16, "'")
       end subroutine

       subroutine sub2
         integer(4) i(2)
         common /blk/ i
         print 2, 'sub2:', i
2        format(A, 2("z'", z8.8, "'", 1x))
       end subroutine

       program main
         call sub1
         call sub2
       end program




在上述代码中,j 和 i 共享存储空间并具有不同的种类。该程序的输出显示 i 的元素在大端和在小端上的排序是不一样的。在大端上,运行程序产生以下输出:
1
2
sub1: z'0001020304050607'
sub2: z'00010203' z'04050607'




在小端上,运行程序产生以下输出:
1
2
sub1: z'0001020304050607'
sub2: z'04050607' z'00010203'




ENTRY 语句当函数的结果有不同的特点时,函数的结果及其 ENTRY 语句之间的存储关联就会出现。在下面的程序中,f 和 g 是存储关联的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function f(a)
double precision a, f
real g
entry g(a)
f = a
end function

program main
interface
   function f(a)
     double precision a, f
   end function
   function g(a)
     double precision a
     real g
   end function
end interface
double precision x
x = z'0001020304050607'
print '(z16.16)', f(x)
print '(z8.8)', g(x)
end program




在大端上,g是一个单精度实数,是双精度  f 最大的一半存储关联。因此,在大端上的输出为:
1
2
0001020304050607
00010203




在小端上,g与  f 最小的一半存储关联。因此,在小端上的输出为:
1
2
0001020304050607
04050607




参数关联在 FORTRAN 77 样式中的调用没有使用显式接口,而是依靠用户传递正确的类型。在大端上,对于某些不符合要求的程序,虽然实际参数和伪参数不匹配,但仍然可以运行成功。请考虑下面的程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
       program main
         integer :: i = 1
         character(5) :: c = 'abcd'
         integer(2) :: h = 2
         real(8) :: d = 1.0

         call hexprint(i, 4)
         call hexprint(c, 5)
         call hexprint(h, 2)
         call hexprint(d, 8)
       end program

       subroutine hexprint(buffer, size)
         character(8) buffer
         integer size
         print 100, buffer(1:size)

100      format (z<2 * size>.<2 * size>)
       end subroutine




该程序是不符合要求的,因为它将多种整数种类的实际参数与字符类型的伪参数关联。该程序没有使用显式接口,因此,编译器不会检测到错误。在大端上,字符和非字符数据使用了相同的字节顺序,因此,该程序产生了预期的输出。在小端上则不然。为了证明这一点,请看该程序在大端和小端上的输出。
在大端上,该程序产生以下输出:
1
2
3
4
00000001
6162636420
0002
3FF0000000000000




在小端上,该程序产生以下输出:
1
2
3
4
01000000
6162636420
0200
000000000000F03F




格式控制的 I/O在格式控制的 I/O 中,用于读或写 I/O 项的编辑描述符必须与 I/O 项的类型和类型参数相对应。举例来说,如果 A 编辑描述符假定 I/O 项的类型为字符,但用来读或写整数类型的 I/O 项,那么有可能会出现移植问题。例如,请考虑下面的程序:
1
2
3
4
5
6
character(4) file
integer(4) a
a = z'61626364'
write(file, '(A)') a
print *, file
end




在大端上,输出为:
abcd
在小端上,输出为:
dcba
返回列表