使用标准C读取文件遇到的结构体对齐问题及其解决办法
作者:朱金灿
来源:http://blog.csdn.net/clever101
同事使用标准C库读取文件,发现总是读取不对,让我帮忙看一下。
原来他定义了如下一个结构体:
// 定义块的结构
typedef struct {
unsigned short id;
long len;
} Chunk3DS;
然后这样读取文件:
if (fread(&chunk,sizeof(Chunk3DS),1,m_fp)!=1)
{
return FALSE;
}
但是读取的内容总是不对。
我想到结构体内存对齐这档子事,于是我把读取代码改为:
Chunk3DS chunk;
if (fread(&chunk.id,sizeof(unsigned short),1,m_fp)!=1)
{
return FALSE;
}
if (fread(&chunk.len,sizeof(long),1,m_fp)!=1)
{
return FALSE;
}
接着我测试了一下:
int nShortSize = sizeof(unsigned short); // 等于2
int nLongSize = sizeof(long); // 等于4
int SstructSize = sizeof(Chunk3DS); // 等于8
整整差了两个字节,难怪读取的内容不对。现在我发现由于结构体内存对齐的缘故(结构体内存对齐的原理网上的相关文章很多,在这不进行详述),使用fread接口去读一个结构体的缓冲区常常不准确,其实也不科学,因为文件设计者在设计文件时文件的各个成员肯定都是紧挨着的,因此是使用简单类型逐个去读取。
如何解决这个问题呢?如前文所述,使用简单类型逐个去读取肯定是可以的,但是如果文件比较复杂的话,这意味着要写比较多的代码。有没有更好的办法呢?也有,可以将结构体做如下定义:
/* 对齐结构成员到1字节 */
#ifdef __GNUC__
#define GNUC_PACKED __attribute__((packed))
#else
#define GNUC_PACKED
#endif #ifdef __arm
#define ARM_PACKED __packed
#else
#define ARM_PACKED
#endif #if defined(WIN32) || defined(_WIN64)
#pragma pack(1)
#endif
ARM_PACKED
typedef struct {
unsigned short id;
long len;
}GNUC_PACKED Chunk3DS;
#if defined(WIN32) || defined(_WIN64)
#pragma pack()
#endif
参考文献:
使用标准C读取文件遇到的结构体对齐问题及其解决办法的更多相关文章
- c语言_文件操作_FILE结构体解释_涉及对操作系统文件FCB操作的解释_
1. 文件和流的关系 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特定字节数的地方结束,这个特定的字节数可以存储在系统维护的管理数据结构中.当打开文件时,就建立了和文件 ...
- C语言文件操作 FILE结构体
内存中的数据都是暂时的,当程序结束时,它们都将丢失.为了永久性的保存大量的数据,C语言提供了对文件的操作. 1.文件和流 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特 ...
- C++ 读取文本文件内容到结构体数组中并排序
成绩排行:从Score.txt文件读取学生信息,对其进行排序,按回答题数从大到小排,若相等,按分数从小到大排 #include<iostream> #include<fstream& ...
- Golang Json文件解析为结构体工具-json2go
代码地址如下:http://www.demodashi.com/demo/14946.html 概述 json2go是一个基于Golang开发的轻量json文件解析.转换命令行工具,目前支持转换输出到 ...
- 结构体:探析C#文件方式读写结构体
最近直在研究Net Micro Framework字体文件(tinyfnt)由于tinyfnt文件头部有段描述数据所以很想 定义个结构体像VC样直接从文件中读出来省得用流个个解析很是麻烦 没有想到在中 ...
- 函数定义从零开始学C++之从C到C++(一):const与#define、结构体对齐、函数重载name mangling、new/delete 等
今天一直在学习函数定义之类的问题,下午正好有机会和大家共享一下. 一.bool 类型 逻辑型也称布尔型,其取值为true(逻辑真)和false(逻辑假),存储字节数在不同编译系统中可能有所不同,VC+ ...
- const与#define、结构体对齐、函数重载name mangling、new/delete 等
一.bool 类型 逻辑型也称布尔型,其取值为true(逻辑真)和false(逻辑假),存储字节数在不同编译系统中可能有所不同,VC++中为1个字节. 声明方式:bool result; result ...
- C语言中结构体对齐问题
C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...
- 《PHP7底层设计与源码实现》学习笔记2——结构体对齐
书里给了一段代码,假如有个结构体如下: struct test { char a; int b; long c; void* d; int e; cha ...
随机推荐
- 关于使用 IDEA Spring Boot 热部署
1,POM 中引用 <dependency> <groupId>org.springframework.boot</groupId> <artifactId& ...
- 09-01 Java final,多态,抽象类,接口
final /* final可以修饰类,方法,变量 特点: final可以修饰类,该类不能被继承. final可以修饰方法,该方法不能被重写.(覆盖,复写) final可以修饰变量,该变量不能被重新赋 ...
- java重点知识
一.java基本知识点 java是由SUN公司在1995年推出的,在2009年SUN公司又被甲骨文公司收购,所以甲骨文公司获得java版权.其底层是由C语言写的,java分为三个体系: JavaSE, ...
- C# 多线程学习系列二
一.关于前台线程和后台线程 1.简介 CLR中线程分为两种类型,一种是前台线程.另一种是后台线程. 前台线程:应用程序的主线程.Thread构造的线程都默认为前台线程 后台线程:线程池线程都为后台线程 ...
- 基于sql service会话共享,实现SSO
1:session的存储基于sql service数据库来存储 2:修改sql service中会话管理的系统存储过程 3:实现几个站点的会话共享 4:应用共享会话,实现单点登录
- ecshop 安装出错gd_version
678: static function gd_version()
- Ansible-安装-秘钥-部署-使用
本文转自:https://www.cnblogs.com/ylqh/p/5902259.html ansiblemaster:192.168.74.146 ansibleslave1 :192.168 ...
- Android so 文件进阶<三> so文件的简单加密
0x00 前言 之前的两篇文章从链接视图和执行视图分析了elf文件的大致结构,这篇文章主要内容是对于so文件进行简单的加密工作,针对Ida等静态分析工具的分析,一旦开始动态调试就应该很容易就可以du ...
- PHP self this parent
{一}PHP中this,self,parent的区别之一this篇 面向对象编程(OOP,Object OrientedProgramming)现已经成为编程人员的一项基本技能.利用OOP的思想进行P ...
- FineUI开源版(ASP.Net)初学手册
女朋友鄙视我原创少... 1.下载 进入官方论坛:http://www.fineui.com/bbs/ 要用到下载源代码和空项目下载 http://fineui.codeplex.com/ http: ...