爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 11810|回复: 10

[求助] fortran读取C语言用unsigned short写的二进制会出问题

[复制链接]

新浪微博达人勋

发表于 2011-10-23 12:40:04 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
最近忙于fortran读取C语言用unsigned short写的二进制文件,发现问题:1.fortran用有符号的变量去“装载”无符号的数值会出现负值。
2.有个type我认为应该是170个字节,但是sizeof(type)得到是1024个字节。

不知道有哪位高人能提出高见!?
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2011-11-30 00:34:23 | 显示全部楼层
本帖最后由 godenflame135 于 2011-11-30 00:37 编辑

问题终于成功解决。(感谢论坛坛主--清风及各位的关注)

问题原因:C语言无符号整形数据可以用fortran读出来,小于零的只要加上65536即可,大于零的就是本身。但是,如果在自定义结构体中含有无符号整形则不太可能再用fortran去读写(如果编程者知道fortran中type字节对齐的话,也有可能用fortran的type去读写),则只能用C语言去读写。

这里要用到一个C语言中自定义结构体非常重要的一个预编译命令(以64位机子为例):

#pragma pack(1)//使结构体按照一个字节一个字节的对齐。
struct   a
{
char a;//1 byte    //no aligment ,it may cost 2 bytes(depend on arch and compiler)
int  b;   //4 bytes
long int c;  //8 bytes
float  d;    //4 bytes
};   // sizeof(a)=17  bytes

//如果不加第一句话:则有可能是18个字节。这样就不能按照字节数去读取写好的文件。
只有这样,才能按照结构体一个字节一个字节的去读取。

密码修改失败请联系微信:mofangbao

新浪微博达人勋

0
早起挑战累计收入
发表于 2011-10-23 13:21:38 | 显示全部楼层
可惜对C不熟悉,只能按自己想的说说,第一个是不是可以考虑在写入的时候写成和fortran一样的类型,fortran中的real或者integer的类型,都是有符号的,用有符号的读取无符号的出错估计可能性太大了,还有c中的short类型占几个bytes呢,fortran中默认的是4个,如果类型和长度都对了,估计就不会出错了吧。

第二个问题我没看明白,你说的type是指的是一个数据,还是指的fortran中的type类,我用的msf4.0的fortran编译器,90的语法,没能识别sizeof()这个函数,不过用size()函数可以取数组的长度
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2011-10-23 15:59:13 | 显示全部楼层

回复问题1:fortran如果定义一个integer*4去装载 C语言的unsigned short的时候,读取的时候会按照4个字节去读,而不是按照2个字节去读。如果这样,会全乱套的。很是纠结啊!
回复问题2: sizeof()不仅可以取数组的长度,而且可以取结构体TYPE的长度,但是结构体在被编译的时候,编译器会默认给它按照4字节或者8字节对齐(编译器不同,对齐字节也会不同)。这样,结构体中的变量之间可能会出现空白字节,这也就是后来sizeof(type A)的时候会出现总字节数大于结构体本身长度的现象。如:
TYPE A
   char        a1
  integer*2  b1
  real*4       c1

end TYPE


这里我们认为结构体A的大小应为7字节,然而编译器可能认为 sizeof(type A)= 12字节。这就是问题所在。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

0
早起挑战累计收入
发表于 2011-10-23 16:06:07 | 显示全部楼层
第一个的话你在fortran是可以指定类型的长度的,比如两字节的整型:integer(2)  或者  integer*2或者integer(kind=2),最后一种是90的语法,前面两种是77可以支持的,但是你c用无符号的写出的话,可能还是会有问题。
第二个你确定是sizeof()函数?为啥我看的是size函数呢,你这个c写出fortran读入虽然我不清楚是为什么这么用,也相当于混编了,混编中最纠结的就是数据类型的问题,最好使用两种语言中都有的而且长度相同的类型,类似结构体这种复杂的类型能不能就不用了
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2011-10-28 19:15:34 | 显示全部楼层
mofangbao 发表于 2011-10-23 16:06
第一个的话你在fortran是可以指定类型的长度的,比如两字节的整型:integer(2)  或者  integer*2或者intege ...

第一个问题可以顺利解决,如果fortran去读c写的unsigned short(2字节)二进制文件,读出来的变量(2字节)数值大于等于0,则就是这个数,如果小于零,加上65536,即可得到在c里面unsigned的数。
第二问问题:type类型不能按照一个字节对齐,那么读出来的数值就不是正确的。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2017-8-29 15:58:43 | 显示全部楼层
经试验在结构体中也可以用第一种方法解决,谢谢楼主
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2017-8-30 10:37:22 | 显示全部楼层
谢谢分享,以前也碰到这个问题,没有解决掉。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2017-10-23 18:24:47 | 显示全部楼层
关于不能按一个字节对齐的问题,ifortran有个命令 ,可以设置recl为一个自己,assume:byterecl。。。。其他编译器是不是也可以设置以及怎么设置就不知道了。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2017-12-12 10:43:32 | 显示全部楼层
taotao 发表于 2017-10-23 18:24
关于不能按一个字节对齐的问题,ifortran有个命令 ,可以设置recl为一个自己,assume:byterecl。。。。其他 ...

更新一下,fortran里有个sequence的命令,在type下面加上这个,就是一个字节一个字节读取。类似C语言的pragma pack。
密码修改失败请联系微信:mofangbao
您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表