但没有编译器支持 24 位的整数类型。而有很多数据却恰恰采用了 24 位整型来存储。对于这种数据,我们需要进行一定的技巧和转换来实现读取。
最直接的办法,是通过内存里的延展,使其读取后,延展为 32 位的整型,并在内存中后续参与计算。
程序运行如下,将 e5ac23 这个 24 位数据写入 t.bin,并读出成 2338021

第一步:
为了能利用 stream 流文件读写,我们定义一个大小为 4 的字符数组 str,取其片段 str(1:3) 进行读取,这样就可以保证读取的是 24 位数据。如果您读取的数据是大端(big-endian)的,则更改为 str(3:1:-1) 反向读取即可。
第二步:
利用 transfer 函数,把 str 字符数组,直接转换成 32 位整型 n 。注意 transfer 函数的作用是强制转换,而不是像内部文件转换那样,考虑字符串代表的数字意义。
第三步:
由于 24 位数据,最高位第24位,表示正负。而直接转换成 32 位后,不能再具有正负的意义。因此,我们需要把 24 位数据左移 8 位,可以利用 ishft 函数实现。
左移可以确保正负号归位。但同时会令整型数值的绝对值增加 2**8 倍。因此左移后需要除以 2**8。
如果关于位操作比较难理解。那么也可以理解这句纯数字计算的算式:
if ( n > (2**23-1) ) n = n - 2**24
其含义是:如果 n 的大小超过了 24 位数据正半部分的上限,就令其减少 2**24 。
这样做的原因是 24 位扩展到32位之后,由于高位为零,始终是正数。这相当于把 24 位数据可以表达的范围由 0 至 2**24 更改到 -2**23 至 2**23-1 (这样做的前提是 str(4) = char(0) ,即高位初值为 0)
代码如下:
01 | Program www_fcode_cn |
02 | Implicit None |
03 | Character :: str ( 4 ) |
04 | Integer :: n |
05 | Open ( 12 , File = "t.bin" , access = 'stream' , form = 'unformatted' ) |
06 | Read ( 12 ) str ( 1 : 3 ) !//如果是大端,则 str(3:1:-1) |
07 | n = transfer ( str , n ) |
08 | n = ishft ( n , 8 ) / 2 * * 8 |
09 | ! if ( n > (2**23-1) ) n = n - 2**24 !如果上句不容易理解,也可以理解此句代码 |
10 | write ( * , '(g0)' ) n |
11 | End Program www_fcode_cn |