# kingofark's Ineffective C/C++：自白2：有符号、无符号还有位运算，我的天！

26 篇文章 1 订阅

Ineffective C/C++ : The Confession of A Novice
《Ineffective C/C++ ：一个低手的自白》

by K ][ N G of @ R K

[声明：kingofark并非高手，在论述中所举的例子未必就可取，也未必就是很好的做法。所有例子仅仅是为了说明某些问题，并不具有代表性。kingofark自知才浅，欢迎大家提出批评，指出错误。]

Item 2: Signed and Unsigned and Bit Operation, oh my!

[问题]：这个函数有什么问题吗？

/
/**
* 本函数将两个16比特位的值连结成为一个32比特位的值。
* 参数：sHighBits 高16位
*       sLowBits  低16位
* 返回：32位值
**/
long CatenateBits16(short sHighBits, short sLowBits)
{
long lResult = 0; /* 32位值的临时变量*/

/* 将第一个16位值放入32位值的高16位 */
lResult = sHighBits;
lResult <<= 16;

/* 清除32位值的低16位 */
lResult &= 0xFFFF0000;

/* 将第二个16位值放入32位值的低16位 */
lResult |= (long)sLowBits;

return lResult;
}
/

[问题的发现]：

/
int main()
{
short           sHighBits1  = 0x7fff;
short           sHighBits2  = 0x8f12;
unsigned short  usHighBits3 = 0xff12;
short           sLowBits1   = 0x7bcd;
long            lResult  = 0;

printf("[sHighBits1 + sLowBits1]/n");

lResult = CatenateBits16(sHighBits1, sLowBits1);
printf("lResult = %08x/n", lResult, lResult);

lResult = CatenateBits16(sHighBits2, sLowBits1);
printf("lResult = %08x/n", lResult, lResult);

lResult = CatenateBits16(usHighBits3, sLowBits1);
printf("lResult = %08x/n", lResult, lResult);
}
/

[sHighBits1 + sLowBits1]
lResult = 7fff7bcd
lResult = 8f127bcd
lResult = ff127bcd

“郁闷！”你说，“这个函数怎么会有问题呢！？”

/
int main()
{
short           sHighBits1  = 0x7FFF;
short           sHighBits2  = 0x8F12;
unsigned short  usHighBits3 = 0x8F12;

short           sLowBits1  = 0x7BCD; //你实际使用的参数
short           sLowBits2  = 0x8BCD; //你实际使用的参数

long            lResult  = 0;

printf("[sHighBits1 + sLowBits1]/n");

lResult = CatenateBits16(sHighBits1, sLowBits1);
printf("lResult = %08x/n", lResult, lResult);

lResult = CatenateBits16(sHighBits2, sLowBits1);
printf("lResult = %08x/n", lResult, lResult);

lResult = CatenateBits16(usHighBits3, sLowBits1);
printf("lResult = %08x/n", lResult, lResult);

printf("/n[sHighBits1 + sLowBits2]/n");

lResult = CatenateBits16(sHighBits1, sLowBits2);
printf("lResult = %08x/n", lResult, lResult);

lResult = CatenateBits16(sHighBits2, sLowBits2);
printf("lResult = %08x/n", lResult, lResult);

lResult = CatenateBits16(usHighBits3, sLowBits2);
printf("lResult = %08x/n", lResult, lResult);

return 0;
}
/

[sHighBits1 + sLowBits1]
lResult = 7fff7bcd
lResult = 8f127bcd
lResult = 8f127bcd

[sHighBits1 + sLowBits2]
lResult = ffff8bcd          //oops!
lResult = ffff8bcd          //oops!
lResult = ffff8bcd          //oops!

[X档案的真相]：

/
long CatenateBits16(short sHighBits, short sLowBits)
{
long lResult = 0; /* 32位值的临时变量*/

/* 将第一个16位值放入32位值的高16位 */
lResult = sHighBits;
lResult <<= 16;

/* 清除32位值的低16位 */
lResult &= 0xFFFF0000;

/* 将第二个16位值放入32位值的低16位 */
lResult |= (long)sLowBits;     //注意这一句！！！！

return lResult;
}
/

printf("sLowBits = %04x/n", sLowBits);

sLowBits = 0x7bcd 时，打印结果为

sLowBits = 7bcd

sLowBits = ffff8bcd

0xffff8bcd

0xffff8bcd

0x00007bcd

[教训：在某些情况下作位运算和位处理的时候，考虑使用无符号数值——因为这个时候往往不需要处理符号。即使你需要的有符号的数值，那么也应该考虑自行在调用CatenateBits16()前后做转换——毕竟在位处理中，有符号数值相当诡异！]

/
unsigned long CatenateBits16(unsigned short sHighBits, unsigned short sLowBits)
{
long lResult = 0;

/* 将第一个16位值放入32位值的高16位 */
lResult = sHighBits;
lResult <<= 16;

/* 清除32位值的低16位 */
lResult &= 0xFFFF0000;

/* 将第二个16位值放入32位值的低16位 */
lResult |= (long)sLowBits & 0x0000FFFF;

return lResult;
}
/

[kingofark的收获]：

• 0
点赞
• 0
收藏
觉得还不错? 一键收藏
• 打赏
• 0
评论
08-11 1727
09-01 75
05-18 7052
05-28 6303
12-07 6194
09-14 6123
07-10 5965
10-17 3829
05-04 2515
07-07 2447
03-29 2140
07-31 2024

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

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

kingofark

¥1 ¥2 ¥4 ¥6 ¥10 ¥20

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