union简介
union常见于C语言嵌入式开发中,union中的数据分享同一段内存,大小与最大的数据类型一致。
union应用
查看浮点数的16进制表示:
#include<stdio.h>
#include <stdint.h>
uint32_t float2int(float a){
union{
float a;
uint32_t b;
}u;
u.a = a;
return u.b;
}
int main(){
float num = 1.5;
printf("%x\n", num);
printf("%x\n",float2int(num));
return 0;
}
输出:
//这里的输出是乱的,运行不同次输出结果不一样
d6009ab8
//这里的输出是符合IEEE754标准的
3fc00000
3fc00000 转换为二进制 0011 1111 1100 0000 0000 0000 0000 0000 0,01111111,100 0000 0000 0000 0000 0000 指数位 -127为0 尾数位个位补1变为1.1,转为10进制1.5。 最终结果1.5*2^0 = 1.5
为啥是乱的?个人解释如下,如有专业人员还望指正: 查看汇编代码
gcc union.c -S
ls
cat union.s
main:
stp x29, x30, [sp, -32]!
add x29, sp, 0
fmov s0, 1.5e+0
str s0, [x29, 28]
ldr s0, [x29, 28]
fcvt d0, s0
adrp x0, .LC0
add x0, x0, :lo12:.LC0
bl printf
ldr s0, [x29, 28]
bl float2int
mov w1, w0
adrp x0, .LC0
add x0, x0, :lo12:.LC0
bl printf
mov w0, 0
ldp x29, x30, [sp], 32
ret
先看下面一段,将数据读入s0,(str后ldr,转入外存再转入内存,可能与内外存数据一致有关)然后利用fcvt指令转换位double型存入d0。
fmov s0, 1.5e+0
str s0, [x29, 28]
ldr s0, [x29, 28]
fcvt d0, s0
adrp x0, .LC0
而我们的printf,输出类型位"%x",为整数,所以printf函数找不到d0寄存器(存储浮点数的寄存器),找错寄存器位置导致的。 2.大小端转换
#include<stdio.h>
#include <stdint.h>
uint32_t big2low(uint32_t num){
union{
uint32_t num;
uint8_t base[4];
}u;
u.num = num;
uint32_t res = 0x00000000;
for(int i = 0; i < 3; i++){
res = (res | u.base[i]) << 8;
}
res = (res | u.base[3]);
return res;
}
int main(){
uint32_t num = 0x12345678;
printf("%x\n", num);
printf("%x\n",big2low(num));
return 0;
}
编译运行
12345678
78563412
|