读取数据与地址对齐

读取数据与地址对齐

 
在chinaunix呆久了,便想在这里记录一些想法,也整理一下以前零散的记录,希望能和大家共进步。此篇文章也作为开博第一回吧。
 
今天翻看一本书,看到了代码移植需要注意的若干问题,其中提到数据对齐,让我想起遇到的x86和ARM平台一些小区别。
有时候我们需要强制转换类型以便得到我们期望的数据,例如
 

char data[10]= {1,2,3,4,5,6,7,8,9,0};
unsigned int d[4];
d[0] = *(unsigned int *)&data[0];

在linux内核中有get_unaligned()宏定义,让你跨平台时使用。此函数有什么作用呢?
我们不妨来看看它的定义:

asm-i386/unaligned.h: 
    #define get_unaligned(ptr) (*(ptr))


asm-arm/unaligned.h:
183 #ifndef __ARMEB__
184 #define get_unaligned __get_unaligned_le
185 #define put_unaligned __put_unaligned_le
186 #else
187 #define get_unaligned __get_unaligned_be
188 #define put_unaligned __put_unaligned_be
189 #endif

再看__get_unaligned_le:

54 #define __get_unaligned_le(ptr) \
 55 ({ \
 56 __typeof__(*(ptr)) __v; \
 57 __u8 *__p = (__u8 *)(ptr); \
 58 switch (sizeof(*(ptr))) { \
 59 case 1: __v = *(ptr); break; \
 60 case 2: __v = __get_unaligned_2_le(__p); break; \
 61 case 4: __v = __get_unaligned_4_le(__p); break; \
 62 case 8: { \
 63 unsigned int __v1, __v2; \
 64 __v2 = __get_unaligned_4_le((__p+4)); \
 65 __v1 = __get_unaligned_4_le(__p); \
 66 __v = ((unsigned long long)__v2 << 32 | __v1); \
 67 } \
 68 break; \
 69 default: __v = __bug_unaligned_x(__p); break; \
 70 } \
 71 __v; \
 72 })

再看__get_unaligned_4_le:

48 #define __get_unaligned_4_le(__p) \
 49 (__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)

我们看到X86平台很简单,就是指针操作。而arm平台需要用字节移位相与的方式。
理由很简单,ARM是要求对齐的,跟它的体系结构有关。想得到正确数据用memcpy或者用字节移位相与的方法。我想我们在编程的时候用指针读取数据的时候满多的,如果不注意有时就可能出现莫名其妙的现象。

总之,当你把代码移植到不同平台时对于这一点需要额外注意。


翻看了以前的日记,看到在ADS1.2中试验结果:

char data[10]= {1,2,3,4,5,6,7,8,9,0};
unsigned int d[4];

d[0] = *(unsigned int *)&data[0];
d[1] = *(unsigned int *)&data[1];
d[2] = *(unsigned int *)&data[2];
d[3] = *(unsigned int *)&data[3];

printf("d[0] is 0x%08x\n", d[0]);
printf("d[1] is 0x%08x\n", d[1]);
printf("d[2] is 0x%08x\n", d[2]);
printf("d[3] is 0x%08x\n", d[3]);
结果如下:
d[0] is 0x04030201
d[1] is 0x01040302
d[2] is 0x02010403
d[3] is 0x03020104



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值