c - 向左旋转并向右旋转以使用 C 中的(带符号短)强制转换进行符号扩展

标签 c casting rotation unsigned signed

之前,我有以下 C 代码,通过该代码,我打算在强制转换为变量“sample_unsigned”的“signed Short”之后对变量“sample”进行符号扩展。

unsigned short sample_unsigned;
signed short sample;

sample = ((signed short) sample_unsigned << 4) >> 4;

在二进制表示中,我希望“样本”的最高有效位重复 4 次。例如,如果:

sample_unsigned = 0x0800 (corresponding to "100000000000" in binary)

我理解“样本”的结果应该是:

sample = 0xF800 (corresponding to "1111100000000000" in binary)

但是,“sample”总是与“sample_unsigned”相同,我必须按如下方式拆分赋值语句,这有效。为什么会这样?

sample = ((signed short) sample_unsigned << 4);
sample >>= 4;

最佳答案

你的方法行不通。无法保证右移会保留该符号。即使如此,它也只适用于 16 位 int。对于 >=32 位 int ,您必须手动将符号复制到高位,否则它只会来回移动相同的数据。一般来说,有符号值的位移位至关重要 - 有关详细信息,请参阅[标准]( http://port70.net/~nsz/c/c11/n1570.html#6.5.7。某些星座会调用未定义的行为。最好避免它们并仅使用无符号整数。

但是,对于大多数平台,以下方法都有效。它不一定更慢(在 16 位 int 平台上,它可能更快):

uint16_t usample;
int16_t ssample;

ssample = (int16_t)usample;
if ( ssample & 0x800 )
    ssample |= ~0xFFF;

转换为int16_t是实现定义的;您的编译器应指定它是如何执行的。对于(几乎?)所有最近的实现,没有执行额外的操作。只需在生成的代码或编译器文档中进行验证即可。逻辑或依赖于使用 2 补码的 intX_t,这是由标准保证的 - 而不是标准类型。

在 32 位平台上,可能存在用于符号扩展的内在指令(例如 ARM Cortex-M3/4 SBFX)。或者编译器提供了一个内置函数。根据您的用例和速度要求,可能适合使用它们。

更新:

另一种方法是使用位域结构:

struct {
    int16_t val : 12;    // assuming 12 bit signed value like above
} extender;

extender.val = usample;
ssample = extender.val;

这可能会导致使用我上面建议的相同汇编器指令。

关于c - 向左旋转并向右旋转以使用 C 中的(带符号短)强制转换进行符号扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33960826/

相关文章:

.net - 在 VB.NET 中将 bool 值转换为字节

javascript - 使用 JS 考虑旋转调整多个对象的大小

c - 查找二维数组的最大大小

将特定数组元素与 C 中具有 "if"的字符串进行比较?

c# - 泛型显式转换

types - 强制转换产生无效指针的函数引用?

iphone - 旋转 UIBarButtonItem

c++ - 如何在 OpenGL 中绘制 3D vector ?

c - C 中的位操作 - 左移以删除最高有效位

c - 如何找到对列表中所有有重叠的对?