我在内置库中找到了一些需要扩展的代码。
但它似乎已损坏:
#define BSWAP16(__x) ((((__x) >> 8) | ((__x) << 8)))
与以下功能不同:
__builtin_bswap16()
该程序证明了这一点。
#include <stdio.h>
#define BSWAP16(__x) ((((__x) >> 8) | ((__x) << 8)))
int main(int argc, char* argv[])
{
unsigned short a = (unsigned short)BSWAP16(0xff00);
unsigned short b = __builtin_bswap16(0xff00);
short c = (short)BSWAP16(-8);
short d = __builtin_bswap16(-8);
printf("a=%04x, b=%04x, c=%04x, d=%04x\n", a,b,c,d);
return 0;
}
输出:
a=00ff, b=00ff, c=ffffffff, d=fffff8ff
我不想要答案告诉我应该使用endian.h或__builtin_bswap16。在此内部库在此平台/编译器配置上使用的目标平台上,我正在触发此默认代码,该代码默认使用上述宏。
所以我的问题是。为什么对负数不起作用?
如果我将-8表示为0xfff8的短值,则它可以正常工作。
所以我想这与内部转换为int有关。
如何修复此宏才能正常工作?
从草案C99标准部分的6.5.7
按位移位运算符表示(强调我的前进),向左移负数是不确定的行为:
E1 << E2的结果是E1左移E2位的位置;空位用零填充。如果E1具有无符号类型,则结果的值为E1´2E2,与结果类型中可表示的最大值相比,模减少了1。如果E1具有带符号的类型和非负值,并且E1´2E2在结果类型中可表示,则这就是结果值;否则,行为是不确定的。
因此,的左移结果-8
是不可预测的。强制转换为unsigned short应该可以解决以下问题:
BSWAP16((unsigned short)-8)
-8
是一个整数常量(原义),由于它没有后缀,因此它是一个int值,因为int可以采用它的值。假设32-bit
int和twos补码将具有以下值:
FFFFFFF8
强制转换为unsigned short将删除不需要的较高位。强制转换为unsigned int将无济于事,因为它将保留较高的位。
右移负数也是实现定义:
E1 >> E2的结果是E1右移E2位的位置。如果E1具有无符号类型,或者E1具有带符号类型和非负值,则结果的值是E1 / 2E2商的整数部分。如果E1具有带符号的类型和负值,则结果值是实现定义的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句