你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【没准我火星了】union的使用及一个缺陷

[复制链接]
amet 发布时间:2015-11-11 21:25
不知道大家在写程序的时候用不用union,之前我只拿来当前后相关性非常强的define来用,有时也和书上一样,存储绝对不会一起出现的值。0 u9 |# G+ {% i, @: ^' H) N
之前看M4的SIMD指令时发现很多操作涉及到数据的封装,把两个16位数值放到一个32位变量的高位和低位里。开始的想法是写个16位数组然后强制类型转换为32位读出。后来看了《C专家编程》,发现可以这么写
4 e5 G) u6 w* Z$ s% L; b9 o( ?
# h" Q% @/ R! U; T* ~
  1. union simdq{
    " \7 e( k  p1 ~0 L4 ~+ d9 b) Z
  2.     int32_t data;
    & l# t+ u9 P, I: `- h) W( w
  3.     int16_t dbyte[2];
复制代码
以下是PC测试程序(同时给2个数乘2,我随便想的一个),也通过32试验
6 o# @, o. P% @$ ~" p4 a7 H
  1. #include <stdio.h>
    8 C2 a9 c, ?9 x+ \# |6 }: }  B
  2. #include <stdint.h>  k$ n9 R! H7 J5 U
  3. int/ T1 c. Q* q, q
  4. main(int argc,char * argv[]){7 e" @5 n1 T  u" @, N
  5.     union simdq{) B/ K! R3 p- g
  6.         int32_t data;1 j& d$ c, X4 H$ I3 N! f/ Z2 f
  7.         int16_t dbyte[2];
    9 |) `+ m: B5 c) S
  8.     }test;+ b4 `3 W! s1 a/ t, k0 m/ z# g8 a
  9.     test.dbyte[0]=1234;) i! N+ J5 J+ C) H# {
  10.     test.dbyte[1]=-5678;
    6 h  M2 I# P3 L$ ?+ G5 a, Z
  11.     printf("test.dbyte[0]= %x\ntest.dbyte[1]= %x\n",test.dbyte[0],test.dbyte[1]);2 e. n/ _" a2 J
  12.     printf("test.data    = %x\n",test.data);& f0 d+ E, M$ w" I8 s! ~  p
  13.     test.data*=2;6 L' U" i4 I/ q- g
  14.     printf("test.dbyte[0]= %x\ntest.dbyte[1]= %x\n",test.dbyte[0],test.dbyte[1]);
    ' S, j( [+ G5 V! O/ }  [( I5 m
  15.     printf("test.data    = %x\n",test.data);
    * |- Q" _8 o  b& C2 `( ^- ]
  16.     return 0;
      n0 i% r! G& Q! _( ^' b
  17. }
复制代码
返回$ B* D2 f* d  g7 Z2 {" F7 _
  1. test.dbyte[0]= 1234
    3 C" \0 D; h% o6 x: O
  2. test.dbyte[1]= -56781 g9 W! W$ f8 g
  3. test.data    = -372112174
    % o  L3 T/ g. s4 F. d! E) K
  4. test.dbyte[0]= 2468
    1 p3 u( F4 ]8 p+ \
  5. test.dbyte[1]= -11356
    $ H8 l& j4 T( q
  6. test.data    = -744224348
复制代码
8 X- d! r: h9 Q( k4 C" W
如果使用16进制,则需要把类型改成 unsigned int ,否则若最高一位为1,读取值会自动扩展(用printf和%x看起来似乎是这样(而且无法通过强制类型转换解决(例如dbyte[1]=0xFFFFACF0(期望值应该是0xACF0(非常诡异(希望高手解答(也是和大家交流分享知识)))))))7 o- z/ \$ ]8 G$ j; \

. ?; s7 U* `6 s; ]' zMCU:STM32F401 + Keil v5* H+ y5 C7 _  F/ _# n/ Q1 b
PC   :Intel core     + clang 3.7.0
0 M/ ^. v( Q- O& M9 t2 F, e' [$ p1 v7 @0 N- H
赞 收藏 1 评论5 发布时间:2015-11-11 21:25

举报

5个回答
zhoupxa 回答时间:2015-11-12 09:25:35
一点都不诡异,要想用union实现16位操作对32位数的MSW和LSW的存取,只能用16位无符号数,如此定义:' S! T7 f- h+ O' A- U
uint16_t  dword[2];
+ p. l' ~: i3 ]8 `: @int32_t    data;
me浩 回答时间:2015-11-12 09:25:36
顶顶顶顶
amet 回答时间:2015-11-12 10:24:12
zhoupxa 发表于 2015-11-12 09:25
- O; u- L5 C0 e  j5 F% r& x一点都不诡异,要想用union实现16位操作对32位数的MSW和LSW的存取,只能用16位无符号数,如此定义:
4 I5 ^( x' g1 huint16 ...
0 b. `; i( r, X) ?, _4 |5 `
受教了,那我使用16位负数的时候是否会存在相应的风险
yanhaijian 回答时间:2015-11-12 10:30:48
是的,这里面涉及到对齐的问题。
aabird 回答时间:2015-11-12 10:35:19
这个想法很好,但是我从来没有这方面的想法
: G( M% L+ z9 S
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版