打印
[应用相关]

union的使用及一个缺陷

[复制链接]
743|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
laocuo1142|  楼主 | 2021-4-12 09:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
不知道大家在写程序的时候用不用union,之前我只拿来当前后相关性非常强的define来用,有时也和书上一样,存储绝对不会一起出现的值。
之前看M4的SIMD指令时发现很多操作涉及到数据的封装,把两个16位数值放到一个32位变量的高位和低位里。开始的想法是写个16位数组然后强制类型转换为32位读出。后来看了《C专家编程》,发现可以这么写

  • union simdq{
  •     int32_t data;
  •     int16_t dbyte[2];

复制代码

以下是PC测试程序(同时给2个数乘2,我随便想的一个),也通过32试验
  • #include <stdio.h>
  • #include <stdint.h>
  • int
  • main(int argc,char * argv[]){
  •     union simdq{
  •         int32_t data;
  •         int16_t dbyte[2];
  •     }test;
  •     test.dbyte[0]=1234;
  •     test.dbyte[1]=-5678;
  •     printf("test.dbyte[0]= %x\ntest.dbyte[1]= %x\n",test.dbyte[0],test.dbyte[1]);
  •     printf("test.data    = %x\n",test.data);
  •     test.data*=2;
  •     printf("test.dbyte[0]= %x\ntest.dbyte[1]= %x\n",test.dbyte[0],test.dbyte[1]);
  •     printf("test.data    = %x\n",test.data);
  •     return 0;
  • }

复制代码

返回
  • test.dbyte[0]= 1234
  • test.dbyte[1]= -5678
  • test.data    = -372112174
  • test.dbyte[0]= 2468
  • test.dbyte[1]= -11356
  • test.data    = -744224348

复制代码


如果使用16进制,则需要把类型改成 unsigned int ,否则若最高一位为1,读取值会自动扩展(用printf和%x看起来似乎是这样(而且无法通过强制类型转换解决(例如dbyte[1]=0xFFFFACF0(期望值应该是0xACF0(非常诡异(希望高手解答(也是和大家交流分享知识)))))))

MCU:STM32F401 + Keil v5
PC   :Intel core     + clang 3.7.0

使用特权

评论回复
沙发
duo点| | 2021-4-12 09:47 | 只看该作者
一点都不诡异,要想用union实现16位操作对32位数的MSW和LSW的存取,只能用16位无符号数,如此定义:
uint16_t  dword[2];
int32_t    data;

使用特权

评论回复
板凳
一刀一级| | 2021-4-12 09:48 | 只看该作者

是的,这里面涉及到对齐的问题。

使用特权

评论回复
地板
七毛钱| | 2021-4-12 09:48 | 只看该作者
这个想法很好,但是我从来没有这方面的想法

使用特权

评论回复
5
diweo| | 2021-4-12 14:32 | 只看该作者
哪里诡异了,结果不都正常的么?

使用特权

评论回复
6
晓伍| | 2021-5-7 09:17 | 只看该作者
自己没用过啊

使用特权

评论回复
7
八层楼| | 2021-5-7 10:17 | 只看该作者
只是他的一个特点吧

使用特权

评论回复
8
观海| | 2021-5-7 10:20 | 只看该作者
一定要注意对齐的方式

使用特权

评论回复
9
guanjiaer| | 2021-5-7 10:22 | 只看该作者
注意一下就可以了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1213

主题

5348

帖子

12

粉丝