发新帖我要提问
12
返回列表
打印

两个byte 转word疑问

[复制链接]
楼主: doob
手机看帖
扫描二维码
随时随地手机跟帖
21
bhsdlmj| | 2009-10-16 12:37 | 只看该作者 回帖奖励 |倒序浏览
这样移有时候编译器很傻.   
圈圈这样一般也会编译出多余指令.
俺一直是指针+大小端条件编译,直接可移植的.  最精简. 修改下大小端定义为0或1就好.
huangqi412 发表于 2009-10-16 12:31


举个例子呗!

使用特权

评论回复
22
bhsdlmj| | 2009-10-16 12:43 | 只看该作者
这样移有时候编译器很傻.   
圈圈这样一般也会编译出多余指令.
俺一直是指针+大小端条件编译,直接可移植的.  最精简. 修改下大小端定义为0或1就好.
huangqi412 发表于 2009-10-16 12:31


能编译出多余指令么?
我觉得一般不会!都是彼此彼此!

使用特权

评论回复
23
bhsdlmj| | 2009-10-16 16:57 | 只看该作者
唉...

不管用任何方法,都得区分大小端,很多CPU还得注意“非对齐”问题
xwj 发表于 2009-10-15 16:45

TempNum = (((UINT16)Buffer[0]) << 8) |  ((UINT16)Buffer[1]) ;
管他大小开端,这样写能有错!有错了,那就是垃圾编译器!

注:俺本贴言论可能有问题,等俺好好看看,再宣判!星期一见!!!

使用特权

评论回复
24
古道热肠| | 2009-10-16 17:18 | 只看该作者
采用圈圈的写法,用乘法不易出错.

使用特权

评论回复
25
想出国打工| | 2009-10-16 20:52 | 只看该作者
奥,不是都说移位效率高吗?
很多2倍乘我都用移位来处理了;
原来又容易出错啊,防不胜防!头痛!

使用特权

评论回复
26
bhsdlmj| | 2009-10-16 21:08 | 只看该作者
奥,不是都说移位效率高吗?
很多2倍乘我都用移位来处理了;
原来又容易出错啊,防不胜防!头痛!
想出国打工 发表于 2009-10-16 20:52

看看汇编就知道效率高不搞了 ??我看都差不多 !!!

再比如:a = (a >> b);
有人爱写成下面的
a >>= b;

理论上讲下面的 效率高 !!!但是实事呢??

现在的编译器 泰牛了   这两个是等价的   不信 你看看 1!!

level prorigryty =  8   is good 1!

有点问题我的电脑  抱歉各位凑合着看

使用特权

评论回复
27
bhsdlmj| | 2009-10-16 21:13 | 只看该作者
xwj 是权威 但是不能盲目相信他   尽管最终证明 本财鸟是错误的 但是 过程却能让基本功扎实  

圈圈的  基本功台牛了  佩服   


我最想知道  难道那个〉〉就没有用处了么???/

使用特权

评论回复
28
zq1987731| | 2009-10-16 23:55 | 只看该作者
何必搞得那么麻烦呢...加法、移位这些都是需要时间的啊...

#define Byte_Ordering 1    // 1 - Big_Endian    0 - Little_Endian

union HalfWord_To_Byte
{
    #if Byte_Ordering
        struct {UINT8 Byte_High, Byte_Low} Byte;
    #else
        struct {UINT8 Byte_Low, Byte_High} Byte;
    #endif
    UINT16 Halfword;
}X;

使用特权

评论回复
29
bhsdlmj| | 2009-10-22 09:15 | 只看该作者
TempNum = (((UINT16)Buffer[0]) << 8) |  ((UINT16)Buffer[1]) ;

我在大小端编译器下都试过了,这种方法我还是觉得是万无一失的啊  和大小端没有关系啊!!!什么情况都对啊!!

哪位高人指点一下!!

使用特权

评论回复
30
bhsdlmj| | 2009-10-22 09:36 | 只看该作者
本帖最后由 bhsdlmj 于 2009-10-22 09:44 编辑

比如说UINT8 Buffer【0】 = 0X12

是担心在大端情况下(((UINT16)Buffer[0]) << 8 由低位向高位移动 于是(((UINT16)Buffer[0]) << 8的值为0么?

所以弄个结构体,因为结构体成员存放时从低地址值存放。

是这样么???

高人指点一下

使用特权

评论回复
31
DC_BOY| | 2009-10-22 09:37 | 只看该作者
还有注意一下 左移 右移 对于单片机效率是比较高

使用特权

评论回复
32
bhsdlmj| | 2009-10-22 09:50 | 只看该作者
太混乱了 不想了!!!虽然结构体所有成员是按照低地址存放,但是对于单个成员来说,如果说一个16位的成员,仍然是按照原来编译器固有的的大小端存放的啊

使用特权

评论回复
33
bhsdlmj| | 2009-10-22 09:51 | 只看该作者
所以搞个结构体 实在是看不出来有什么好处啊!!!

使用特权

评论回复
34
渤海三叠浪| | 2009-10-22 09:59 | 只看该作者
太混乱了 不想了!!!虽然结构体所有成员是按照低地址存放,但是对于单个成员来说,如果说一个16位的成员,仍然是按照原来编译器固有的的大小端存放的啊 ...
bhsdlmj 发表于 2009-10-22 09:50



你说的对!!确实是没有必要搞个结构体!!!圈圈的用乘法还是比较好的。你的方法也很好!!!

使用特权

评论回复
35
xlsbz| | 2009-10-22 11:59 | 只看该作者
让我来终结这个帖子吧

(1)联合体效率是比结构体高,但是联合体要注意大小端的问题 就像28楼和29楼说的。但是并不是所有人都能意识到这个大小端,所以不推荐使用联合体。只有在对效率有严格要求的情况下谨慎的使用。
(2)圈圈的方法
考虑到以后的可移植性,我一般这样写:

TempNum = Buffer[0];
TempNum*=256;
TempNum+=Buffer[1];
computer00 发表于 2009-10-15 17:21

就这个问题本身来说还是不错的,没有什么漏洞
(3)
这种方法
TempNum = (((UINT16)Buffer[0]) << 8) |  ((UINT16)Buffer[1]) ;
也是很好的 ,因为移位指令本身不用考虑大小端问题 比如说Intel80X86/Pentium体系(little-endian)的CPU和Motorola 68K体系(big-endian)中的执行结果是完全相同的。向最常见的keil 、MDK编译器也是如此。
(4)也可以考虑用微软提供的方法
WORD MAKEWORD(
    BYTE bLow,
    BYTE bHigh
);
Parameters
bLow
Specifies the low-order byte of the new value.
bHigh
Specifies the high-order byte of the new value.
Return Value
The return value is a WORD value.
--------------
因为放置了两个byte ,已经很“齐”了,因此理论上所有编译器都会认为是占2个字节

(5)推荐一个微软的另一种做法给个参考
#define MAKEWORD(a, b) ((WORD)(((BYTE)((DWORD_PTR)(a) & 0xff)) | ((WORD)((BYTE)((DWORD_PTR)(b) & 0xff))) < < 8)) 

使用特权

评论回复
36
computer00| | 2009-10-22 21:44 | 只看该作者
当要考虑到对齐、大小端、填充等问题时,结构体+联合体,或者直接强制转换等方式都可能会出问题的(不同的编译器关键字还可能不一样)。写成乘法+加法的方式是移植起来比较可靠的。

使用特权

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

本版积分规则