C中的签名扩展实现

时间:2017-09-09 23:07:05

标签: c sign-extension

好的我已经阅读了很多关于签名扩展的内容,但我对C以及所有'按位运算符'都是全新的。所以我仍然无法弄清楚我应该如何在C中实现它。

我有一个名为getField的函数,它应该在更大的位内返回一块位的值。它需要三个整数:valuehilo以及bool:isSigned作为参数。例如,此调用应返回2:

return getField(9, 5, 2, 0);

除了签名号码外,我的功能有效。在阅读了符号扩展后,我认为我的理解是,如果isSignedtrue,那么我需要添加一些,所以在上面的示例中,解决方案(0010)会成为(111...0010)。这是我处理数字签名的代码(result等于函数在isSignedfalse时返回的内容):

if (isSigned) {
    return (~result) + 1;
}

如果我应该返回2s补码有符号整数,这将有效但遗憾的是,这不是我应该做的。任何帮助表示赞赏。

编辑:以下是该方法的完整代码......

int getField (int value, int hi, int lo, bool isSigned) {
int mask;

//Make Sure 'hi' is the high value
if (hi < lo) {
    int temp = hi;
    hi = lo;
    lo = temp;
}
int numberOfBits = (hi - lo) + 1;

mask = ((1 << numberOfBits) - 1) << lo;
int result = value & mask;

//Get rid of LSB if value is zero
result = result >> lo;

if (isSigned) { //Sign Extension instead of Twos Complement
    return (~0) << numberOfBits | result;
}
else {
    return result;
}

}

(注意:我确实看到了一个与此相似的帖子,我读了它,但我仍然感到非常困惑,所以我决定写一个不同的。抱歉,如果这违反了规则。)

2 个答案:

答案 0 :(得分:-1)

所以我真的不明白你的功能在做什么,但你可以通过以下按位操作得到答案:

int ones = ~0;                  // should give 1111...111111
int shifted_ones = (ones << 4); // should give 1111...110000
result = shifted_ones | result; // should give 1111...110010

// or in one line
result = ((~0) <<4) | result;

我不确定这是否能回答你的问题。显然,班次的数量需要变量。

修改

好的,所以在数学上正确的第一个答案会发出警告(至少在GCC上)。编译器检测从数字末尾移位的位(1)。可能不是真正的生产解决方案,但有点好玩。原始解决方案没有发出警告。

int ones = 0b1111; // make the number of ones the same size as the answer.
result = ~ones | result;

答案 1 :(得分:-1)

你应该使用机器自己的标志扩展功能,你可以通过一些数据类型的转换来实现

int getField(unsigned int data, int from, int to, int s)
{
    // assuming 32 bit ints, add error check, ymmw
    data <<= 32-from;
    if (s)
       return ((int)data) >> (32-(from-to));
    return (data >> (32-(from-to)));
}