多字节变量在内存分配时是低字节在前的,例如,定义一个四字节的变量“int a;”系统给a分配的地址为0x90008542,低字节在前,这个地址就是a的最低字节的地址,那么a的最高字节地址就是0x90008545。
在设备间通讯时,一般获取到的数据都是一个字节一个字节的,比如,通过uart发来的数据,通过IIC从24C02中读取的数据,这些都是一次读取一个字节的。A设备从B设备获取多字节数据时,如果B设备的程序开发人员经验丰富,考虑周到,将低字节放在前面,这固然是可喜可贺的;如果考虑欠缺,先放了高字节,就需要将获取到的数据进行高低字节交换了。
方法一:
最容易想到的就是通过移位将数据重组拿双字节变量来举例:
#include <stdio.h>
int main(void) {
short a;
a = 0x1234;
printf("Before swap a = 0x%x\n",a);
a = (a<<8)|(a>>8); //由于有变量a类型本身的限制,所以计算过程中不需要通过&0xffff之类的运算来限制。
printf("After swap a = 0x%x\n",a);
return 0;
}
程序看起来也很简洁,一行就够了,但是移位指令实际运行时,是通过一次移动1位来实现的,编译后的程序从运行时间和程序空间上都没有什么优势。如果是四字节变量,将会在视觉上造成冲击,如下:
#include <stdio.h>
int main(void) {
int a;
a = 0x12345678;
printf("Before swap a = 0x%x\n",a);
a = (a<<24)|((a<<8)&0xff0000)|((a>>8)&0xff00)|(a>>24); //由于有变量a类型本身的限制,所以计算过程中最高位最高位和最低位不需要通过&0xffff之类的运算来限制。
printf("After swap a = 0x%x\n",a);
return 0;
}
方法二:
利用指针将多字节分割,然后交换数据:
#include <stdio.h>
void swap32(int *data)
{
char *p = (char *)data;
p[0] ^= p[3];
p[3] ^= p[0];
p[0] ^= p[3];
p[1] ^= p[2];
p[2] ^= p[1];
p[1] ^= p[2];
}
int main(void) {
int a;
a = 0x12345678;
printf("Before swap a = 0x%x\n",a);
swap32(&a);
printf("After swap a = 0x%x\n",a);
return 0;
}
从篇幅上看是占用了更多行,但是实际编译生成的代码是比方法一简洁多了,执行时间也较短。
当然也有通过联合体进行交换的方法,不过需要定义一个联合体传递参数,不如指针来的直接。
利用联合体的方法见链接:点击打开链接
希望本文能够对大家有所帮助。