OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7447|回复: 4

小弟对结构体指针和内存分配的理解,恳请大神指教

[复制链接]

119

主题

439

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1185
金钱
1185
注册时间
2015-9-18
在线时间
422 小时
发表于 2015-11-30 10:53:19 | 显示全部楼层 |阅读模式
先上代码,使用的是原子stm32f1系列开发板,开发环境是MDK4.7a;
[mw_shl_code=c,true]struct A { char a; char b; char c; char d; char e; char f; char g; char h; }; struct B  { int a; int b; }; struct C { char a; int  b; }; __packed struct D { char a; int b; }; int main() { struct A temp_A={1,2,3,4,5,6,7,8,}; struct B temp_B={10,20}; struct A *p_A=&temp_A; struct B *p_B=&temp_B; int m = 0; int i = 0; int j = 0; int k = 0; int l = 0; i = sizeof(struct A); j = sizeof(struct B); k = sizeof(struct C); l = sizeof(struct D); m=((struct B *)p_A)->a; } [/mw_shl_code]


1>先说内存分配方面:
问题1:例如struct C,它的2个成员都是按照"字"来进行分配内存,所以大小是8字节
         而在struct D,因为使用了__packed,结果前者使用了"字节"进行分配,后者使用"字"进行分配.
        小弟的疑问是:针对struct A成员全是char类型,为什么全部按照"字节"进行分配(我也没有使用__packed),恳请大神指教~~~
2>结构体指针强制转换
看网上的网友说,指针强制转换,它的转换结果是"临时性的",也就说强制转换的结果只是临时起作用,并没有改变变量的本身类型属性.
如图,m的取值是04030201,这个小弟理解有问题
小弟分析如下:因为temp_A和temp_B是局部变量,是存储在堆栈中的,而堆栈的增长方向是高地址->低地址.
那么struct A成员在内存中的存储也应该是高地址->低地址
高地址
01
02
03
04
05
06
07
08
低地址
因为stm32采用的是小端模式,所以m的值应该是01020304啊?恳请大神指教~~~
电子爱好者
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2015-11-30 13:47:08 | 显示全部楼层
问题1:

对于arm芯片来说(貌似32位芯片都适用),编译器默认情况下变量的地址是4字节对齐的,对于32位芯片这样存储数据比较有效率,所以在结构体C中,你第一个char一般定义在一个4字节的对齐位置上,而距离下一个对齐的位置有3个字节,第二个int占4字节,为了优化访问效率,就会将第二个int放到下一个对齐位置,那就会有3个空白字节,所以才会占用8个字节。c的结构中8个字节应该是 char,空,空,空,int,int,int,int。

而D重新设置了对齐方式“__packed”(一直不知道keil中是这个方式,iar中是#pragma pack(1)),这样就更紧凑一点,那d的结构就是char,int,int,int,int 的5个字节,但这样可以看出当访问int的时候不是4字节对齐(不太熟悉底层,看汇编貌似要访问两次然后拼凑),效率会低。所以在空间足够的情况下,还是采用4字节的方式,当然如果效率损失完全接受,但是对ram限制高,可以使用pack(1) 1字节对齐。
其次D的结构如果是int在前,char在后会更合理,正好对齐,所以结构体设计的时候也会考虑这些要素。

为什么结构体A 的char是按字节来,我个人的理解是char本来就会取4个字节然后再找到对应的字节,所以就把多个char就按1字节对齐就可以,而且char按4字节对齐存放的话,感觉对ram的利用率太低了。

此外发现,如果单独定义变量,在默认的pack情况下,8位的char可以定义在1字节对齐的地址上(所有地址),16位的short int可以定义在两字节对齐的地址上(0x0,0x2,0x04.。。。),32位的int可以定义在4字节对齐的地址上(0x0,0x4,0x8)。
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 1 反对 0

使用道具 举报

119

主题

439

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1185
金钱
1185
注册时间
2015-9-18
在线时间
422 小时
 楼主| 发表于 2015-11-30 10:59:51 | 显示全部楼层
恳请路过的大神指教下,不胜感激~~~
电子爱好者
回复 支持 反对

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2015-11-30 14:02:21 | 显示全部楼层
问题2:
我理解单个数据存放的顺序和栈增长的方向是不相关的,应该只和大小端有关系。
你可以看一下0x200003Ec是不是0x01,而0x200003ed是0x02,在栈中的模型应该是这样的
低地址
0x200003EC     01
0x200003ED     02
0x200003EE     03
0x200003EF     04
0x200003F0     05
0x200003F1     06
0x200003F2     07
0x200003F3     08
高地址

这样小端模式就是地位在低地址,高位在高地址,0x200003EC到0x200003EF这段数据按照int来解读,那就是0x04030201
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复 支持 反对

使用道具 举报

119

主题

439

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1185
金钱
1185
注册时间
2015-9-18
在线时间
422 小时
 楼主| 发表于 2015-11-30 14:03:00 | 显示全部楼层
回复【3楼】ianhom:
---------------------------------
一直蒙受大神教诲,小弟铭记于心~~~
电子爱好者
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-25 18:32

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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