关于C中struct结构体的动态malloc和memcpy的指针操作
2016-04-17 01:17
381 查看
今天碰到一个问题,先贴代码:
输出结果为:
那么这个是为什么呢?
我们先看下地址,结构体的首地址是0x28f1ee8,于0x28f1eeb相差3个字节,也就是说结构体总大小为6,
但是bySignature的大小是3个字节,为什么打印出来的却是[GIF89a],这不是6个字节了吗?
原来是一位,memcpy拷贝了6个字节空间大小的数据到结构体,也就是结构体的6个字节数据都被填充了数据,
有一个重要的标准我们不能忘记,在定义数组时,我们需要在数组最后一个偏移位置填充一个’\0’来标识数组结束,否则在操作数组指针的时候,就可能偏移出去
我们回到结构体,结构体由两个大小为3字节大小的数组组成,在两个数组之间,如果没有’\0’来结束第一个数组,因为结构体第一个参数的地址为结构体首地址,所以就会打印第一个数组时,则会在遇到’\0’,或者到结构体分配大小的末尾结束,从而导致上面的情况
除非cpy的源跟目标的结构是一模一样的,这样才可能不会出现这种情况,但是个人认为一个一个cpy更安全,当然我也觉得可能*还有更好的方法来解决,目前我还没想到*
2.在创建结构体的时候,尽量建立初始化结构体函数,如果存在数组,就应该在数组实际大小的基础上+1,用来填充’\0’,表示数组结束
下面是正确的代码:
结果:
typedef struct Gifheader { char Signature[3]; char Version[3]; gifheader() { Signature[2] = '\0'; Version[2] = '\0'; } }GIFHEADER; OpenGif() { QFile file(qApp->applicationDirPath()+"/gif.gif"); if(!file.open(QIODevice::ReadWrite | QIODevice::Text)) { return; } QByteArray byte = file.readAll(); char* p = byte.data(); struct Gifheader* head = (struct Gifheader*)mallGGoc(sizeof(struct Gifheader)); memset(head,'\0',sizeof(GIFHEADER)); memcpy(head,p,sizeof(struct Gifheader)); qDebug("gif:[%s] version:[%s] phead = [%p] Signature:[%p] Version:[%p]" ,head->Signature,head->Version,head,head->Signature,head->Version); free(head); }
输出结果为:
gif:[GIF89a] version:[89a] phead:[0x28f1ee8] Signature:[0x28f1ee8] Version:[0x28f1eeb]
那么这个是为什么呢?
我们先看下地址,结构体的首地址是0x28f1ee8,于0x28f1eeb相差3个字节,也就是说结构体总大小为6,
但是bySignature的大小是3个字节,为什么打印出来的却是[GIF89a],这不是6个字节了吗?
原来是一位,memcpy拷贝了6个字节空间大小的数据到结构体,也就是结构体的6个字节数据都被填充了数据,
有一个重要的标准我们不能忘记,在定义数组时,我们需要在数组最后一个偏移位置填充一个’\0’来标识数组结束,否则在操作数组指针的时候,就可能偏移出去
我们回到结构体,结构体由两个大小为3字节大小的数组组成,在两个数组之间,如果没有’\0’来结束第一个数组,因为结构体第一个参数的地址为结构体首地址,所以就会打印第一个数组时,则会在遇到’\0’,或者到结构体分配大小的末尾结束,从而导致上面的情况
解决办法:
1.在结构体中存在数组时,我们必须要知道数组的特殊性,所以不能使用memcpy来讲整个结构体块memcpy,除非cpy的源跟目标的结构是一模一样的,这样才可能不会出现这种情况,但是个人认为一个一个cpy更安全,当然我也觉得可能*还有更好的方法来解决,目前我还没想到*
2.在创建结构体的时候,尽量建立初始化结构体函数,如果存在数组,就应该在数组实际大小的基础上+1,用来填充’\0’,表示数组结束
下面是正确的代码:
typedef struct Gifheader { char Signature[4]; char Version[4]; gifheader() { Signature[3] = '\0'; Version[3] = '\0'; } }GIFHEADER; void HImageTool::OpenGif() { QFile file(qApp->applicationDirPath()+"/gif.gif"); if(!file.open(QIODevice::ReadWrite | QIODevice::Text)) { return; } QByteArray byte = file.readAll(); char* p = byte.data(); GIFHEADER* head = (GIFHEADER*)malloc(sizeof(GIFHEADER)); memset(head,'\0',sizeof(GIFHEADER)); memcpy(head->Signature,p,sizeof(head->Signature)-1); memcpy(head->Version,p+3,sizeof(head->Signature)-1); // memcpy(head,p,sizeof(struct gifheader)); qDebug("gif:[%s] version:[%s] phead = [%p] Signature = [%p] Version = [%p]" ,head->Signature,head->Version,head,head->Signature,head->Version); free(head); }
结果:
gif:[GIF] version:[89a] phead = [0x2a71ac8] bySignature = [0x2a71ac8] byVersion = [0x2a71acc]
相关文章推荐
- lcd fb参数如何计算
- LintCode : Inorder Successor in Binary Search Tree
- C++primer 练习15.15
- HDU 1029 Ignatius and the Princess IV(排序取数)
- 设计模式之代理模式
- JQuery学习之旅之显示和影藏
- Python的排列组合运用
- forward的第二种使用方式
- 搭建邮件服务器时设置A/MX记录方法详解
- eclipse字符集编码设置
- 【python小练】图片爬虫之BeautifulSoup4
- laravel中间件-----------middleware
- excel工作薄密码破解/清除
- CentOS7.2系统环境中安装saltstack详细配置过程讲解
- 是什么遮蔽了时寒冰的眼睛
- Code::Blocks配置MSVC2013编译器
- 模拟器常用快捷键
- Python中自定义模块的引用
- 226.[LeetCode]Invert Binary Tree
- Context概述