【转】__attribute__((packed)) 指针传递,赋值错误问题。 - Linux/Unix社区 / 程序开发区
来源:百度文库 编辑:神马文学网 时间:2024/04/29 02:09:09
- xulinguestc
- (凌云)
- 等 级:
- 结帖率:
程序:
===========================
typedef struct AUTO_SUBMIT_ST
{
char cAutoSubmitFlag; // 自动上报开关
unsigned int uiStartTime; // 开始时间
unsigned int uiEndTime; // 结束时间
unsigned int uiTimeCycle; // 周期时间
unsigned int uiLastTime; // 上一次上报时间
}__attribute__((packed))AutoSubmitInfo; // 自动上报信息结构体
void testfun(unsigned int * output, unsigned short input)
{
*output=(unsigned int )input;//函数内 部赋值
printf("%x=%x\n",output,*output);
printf("%x ",*((char*)output+0));printf("%x ",*((char*)output+1));printf("%x ",*((char*)output+2));printf("%x \n",*((char*)output+3));
}
int main(int argn, char *argc)
{
AutoSubmitInfo testdata;
AutoSubmitInfo* pst=&testdata;
testfun(&(pst->uiLastTime), 0xbc);
printf("%x=%x\n",&(pst->uiLastTime),pst->uiLastTime);//外部打印值,和内部赋的值,完全不一样,为什么呢,怎么解决? printf("%x ",*((char*)(&(pst->uiLastTime))+0));printf("%x ",*((char*)(&(pst->uiLastTime))+1));printf("%x ",*((char*)(&(pst->uiLastTime))+2));printf("%x \n",*((char*)(&(pst->uiLastTime))+3));
}
===========================
编 译:
[root@localhost MIT]# arm-linux-gcc test.c
===========================
打 印结果:
[/mnt/nfs]./a.out
内部bffffe59=bc000000
0 0 0 a4
外 部bffffe59=a4000000
0 0 0 a4
- 对我有用[0]
- 丢个板砖[0]
- 引用
- 举报
- 管理
- TOP
- white1977
- (天堂)
- 等 级:
- 对我有用[0]
- 丢个板砖[0]
- 引用
- 举报
- 管理
- TOP
- xulinguestc
- (凌云)
- 等 级:
- 对我有用[0]
- 丢个板砖[0]
- 引用
- 举报
- 管理
- TOP
- white1977
- (天堂)
- 等 级:
你把这个定义成int型 试试。
- 对我有用[0]
- 丢个板砖[0]
- 引用
- 举报
- 管理
- TOP
- xulinguestc
- (凌云)
- 等 级:
- 对我有用[0]
- 丢个板砖[0]
- 引用
- 举报
- 管理
- TOP
- white1977
- (天堂)
- 等 级:
- 对我有用[0]
- 丢个板砖[0]
- 引用
- 举报
- 管理
- TOP
- xulinguestc
- (凌云)
- 等 级:
- 对我有用[0]
- 丢个板砖[0]
- 引用
- 举报
- 管理
- TOP
- white1977
- (天堂)
- 等 级:
typedef struct AUTO_SUBMIT_ST
{
char cAutoSubmitFlag; // 自动上报开关
unsigned int uiStartTime; // 开始时间
unsigned int uiEndTime; // 结束时间
unsigned int uiTimeCycle; // 周期时间
unsigned int uiLastTime; // 上一次上报时间
}__attribute__((packed))AutoSubmitInfo; // 自动上报信息结构体
void testfun(AutoSubmitInfo * output, unsigned short input)
{
output->uiLastTime=(unsigned int )input;//函数内部赋值
}
int main(int argn, char *argc)
{
AutoSubmitInfo testdata;
AutoSubmitInfo* pst=&testdata;
testfun(pst, 0xbc);
}
你可以找一些关于参数指针方面的资料看看。
- 对我有用[0]
- 丢个板砖[0]
- 引用
- 举报
- 管理
- TOP
- xulinguestc
- (凌云)
- 等 级:
http://www.linuxforum.net/forum/showflat.php?Cat=&Board=embedded&Number=535938
在ARM core的平台(StrongARM, 2410, XScale)上,如果企图通过一个独立的指针对某个数
据结构的内部成员域进行定位和访问 时,会遇到下面的问题(注,在IA-32 X86平台不会出现
这样的问题)。
定义一个数据结构:
struct __attribute__((packed)) test {
char c; // 1个字节
short s; // 2个字节
long l; // 4个字节
} st;
packed属性,对应于gcc编译选项 -fpack-struct;
test 的内存布局在该属性的制约下是紧凑的,也就意味着第2、3个成员s、l的起始地址将是
奇地址。
如果另行定义一个独立指针: unsigned long t;
通过“t+偏移字节数”的方式来定位(访问)结构内成员域,则会在强制类型转换t指针来赋值
或者读取相 应成员域时,出现下面的问题:
(假定该结构的起始地址为A0, 则c、s、l的地址各为A0、A1、A3)
1. 编译器版本(arm version):GCC 2.95.2 / 3.2 / 3.3.2
t = (unsigned long) &st;
*((short*)(t+1)) = 0x0201;
期望: 0x01赋于A1字节, 0x02赋于A2字节
实 际: 0x01赋于A0字节, 0x02赋于A1字节,与期望不吻合
*((long*)(t+3)) = 0x08070605;
期 望: 0x05 - 0x08 逐次赋于 A3 - A6 字节
实际: 0x05 - 0x08 逐次赋于 A0 - A3 字节,与期望不吻合
结 论: 基于这些GCC版本,如果对奇地址进行强制类型转换,企图获得"字、双字"的数据类型,
则强制转换后所获得的数据类型,其地址将被自动"优 化"为最近的可被相应对齐模数
(字型数据的对齐模数是2,双字的是4)整除的低位偶地址!
2. 编译器版本(arm version):GCC 2.95.3 / 3.0
t = (unsigned long) &st;
*((short*)(t+1)) = 0x0201;
期望: 0x01赋于A1字节, 0x02赋于A2字节
实际: 0x01赋于A1字节, 0x02赋于A2字节,与期望吻合
*((long*)(t+3)) = 0x08070605;
期望: 0x05 - 0x08 逐次赋于 A3 - A6 字节
实际: 0x05 - 0x08 逐次赋于 A0 - A3 字节,与期望不吻合
结论: 基于这些GCC版本,如果对奇地址进行强制类型转换,企图获得"双字"的数据类型,
则强制转换后所获得的数据类型,其地址将被自动"优化"为最近 的可被相应对齐模数
4整除的低位偶地址!但对字型数据的此类操作,却不会引起这种指针优化。
附,有资料称:
某些 架构上访问数据时有对齐的要求,比如只能从4字节边界上读取一个4字节的数据类型。
IA-32架构没有硬性要求对齐,尽管未对齐的访问降低执行效 率。另外一些架构,比如MIPS、
SPARC、m68k、ARM(
那么有没有一个办法(比如gcc的编译选项,或者一个__attribute__),能制 约上述的这种指针优化,
使其不自动发生!从而使实际操作与期望操作相吻合?
进一步地问,为何不同版本的arm-linux- gcc所编译出的执行码的在这个问题上的表现不一样!?
这后面有更深层的理论背景吗?
================
如 果endian是确定的,我喜欢这样的形式:((unsigned char*)&s)[0] * 256 + ((unsigned char*)&s)[1]
=============================
en,这样把操作分解成基于字节的处 理确实是一个变通的办法,和本人的考虑是一致的;在找不出更好解决方法的情况下,我认为可以有下面3种办法来回避这样的问题:
1. 改变数据源的结构布局,放弃紧凑布局;
代价:增加并浪费了 padding 字节,且既有应用需要重写,以配合结构体内存布局的变化;
2. 改变对结构成员的访问方式,放弃通过独立指针来定位/读写成员域,而直接采用成员名的方式访问;
代价:既有应用程序的改动范围较大;
3. 维持目前的数据源和数据访问方式,而新增一个过渡层,表现形式可以是一组宏,或者内联函数,或
者函数,对结构体内的一切字或双字型数据的访问, 通过这个过渡逻辑被分拆为以字节为基础的操作,
从而回避指针强制类型转换时发生优化;这也同样是nxin的思路!
代价:既有应用程序在访 问结构体成员时的代码形式发生变化,但个人认为这种方法对系统整体代码的
影响是最小的。
可是变通归变通,欢迎大家继续对可能根本 解决此问题的方法进行讨论!谢谢!
- 对我有用[0]
- 丢个板砖[0]
- 引用
- 举报
- 管理
- TOP
- cdqy
- (触电)
- 等 级:
typedef struct {
unsigned char flag; //有效性
int baudrate; //速率
unsigned char serial_num; //端口号
unsigned char parity; //校验
unsigned char sync_mode; //同步方式
unsigned char rtscts; //流控制
unsigned char bytesize; //数据位长度
unsigned char stopbits; //停止位长度
}__attribute__((packed)) S_COMM_PARA;
结 果在对这个结构数组赋值时出现了问题
int i;
S_COMM_PARA com_para[2];
for ( i=0; i<2; i++ )
{
com_para[i]. baudrate = 9600;
com_para[i]. bytesize = 8;
printf("com_para[%d].bytesize=%d\n", i, com_para[i]. bytesize );
printf("i=%d, com_para0].bytesize=%d\n", i, com_para[0]. bytesize );
}
结 果实际打印的是在第二次循环后,com_para[0].bytesize = 2;
【转】__attribute__((packed)) 指针传递,赋值错误问题。 - Linux/Unix社区 / 程序开发区
用dlopen和dlsym得到的函数指针,在dlclose后还能继续使用么? - Linux/Unix社区 / 程序开发区
用GCC将源文件编译成库文件的问题 Linux/Unix社区 / 程序开发区
用GCC将源文件编译成库文件的问题 Linux/Unix社区 / 程序开发区
用GCC将源文件编译成库文件的问题 Linux/Unix社区 / 程序开发区 - CSDN社区 community.csdn.net
Makefile一问:如何修改.o输出文件的输出路径 Linux/Unix社区 / 程序开...
问下关于put_user问题 - Linux/Unix
WebFldrs XP 是什么程序? - 免费软件,绿色软件,linux/unix/win...
linux?下c?程序?段错误?分析
ChinaUnix.net - 写给Linux内核新手-关于Linux内核学习的误区 - 中国Unix技术社区
linux中到底有多少个系统空间堆栈?? Linux/Unix社区 / 内核及驱动程序研究...
Linux系统下C语言编程基础知识介绍 - Linux/Unix社区 / 实用资料发布区
论坛首页 - 中国最大的Linux/Unix技术社区 - IT人的网上社区 - bbs.C...
重视linux/unix
Linux/Unix patch用法 - LINUX/UNIX - boisheng -- Linux笔记
解决linux下java程序(例如applet)中文乱码问题
应用 Valgrind 发现 Linux 程序的内存问题
应用 Valgrind 发现 Linux 程序的内存问题
嵌入式汇编中divl的用法? Linux/Unix社区 / 内核及驱动程序研究区
解决基于tomcat的web应用乱码问题 - J2EE开发者 - web思想社区 关注互联网平台级架构设计,UNIX/LINUX系统管理,项目管理,个人职业规划及RIA,CSS/JS/XML,ASP,
段错误(Segment Fault!)莫名的问题|程序编程
关于指针的问题?
如何安装SUN公司的SOLARIS操作系统------(unix)50分呀!!! Linux/Unix社区 / 系统维护与使用区 - CSDN社区 community.csdn.net
指向指针的指针的一个问题