gpt4 book ai didi

c - C 中的 getField 方法

转载 作者:行者123 更新时间:2023-11-30 18:55:59 25 4
gpt4 key购买 nike

我正在研究一种应该返回字段值的方法。健全性检查示例:如果字段为三位宽且无符号,则结果将是 0 到 7 之间的值,无论值中位的实际位置如何。如果该值有符号,则结果将在 -4 和 3 之间。此外,如果该值有符号,则仅当该字段的最左边位为 1 时,该值才会为负。在这种情况下,该字段必须进行符号扩展(即将左侧所有位设为 1)。我所拥有的逻辑对我来说似乎是正确的,但似乎是错误的。

在我的测试中,当它为 0:somepoint; 时我就得到了正确的结果。当它在某个点时我会失败:某个点

int getField (int value, int hi, int lo, int isSigned) {  
int x = 0;
//int result = 0;
for(int i =lo; i < hi; i++){
x |= (1 << i);
}
if(isSigned == 1){
value |= ~x;
}
else{
value &= x;
}
int finalresult = value >> lo;
return finalresult;
}

最佳答案

而不是

int x = 0;
for(int i =lo; i < hi; i++){
x |= (1 << i);
}

你可以这样做

int x = ((1 << (hi-lo)) - 1) - ((1 << lo) -1);

或从(hi-lo)中添加/减去额外的 1 - 这取决于 hi 位是否为“in”。

为什么?

 1            => 0000 0001
1 << 5 => 0010 0000
(1 << 5) - 1 => 0001 1111

此外,负数位于 U2 中符号,所以如果你想对数字取负,你需要执行 2 个步骤:

  1. 反转所有位
  2. 添加 1

因此value |= ~x还不够(您将反转零,但不会反转其余部分,并且仍然需要添加 1)。您可以简单地用 value ^= (-1) 反转。这就是为什么 somepoint:somepoint 案例不起作用。

我写过类似的东西:

#include <cassert>

int getField(int value, int hi, int lo, int isSigned) {
int result = 0;

assert(hi >= lo);
// let say we are interested in folowing bits:
// (marked as 1)
// value := 0001 1100
// so:
// hi := 5
// lo := 2
// and e.g.:
// isSigned := 1

isSigned = (value >> (hi-1)) & isSigned; // isSigned will be 1 if (it was
// 1 and proper bit is set to 1)
// ((0001 1100) >> 4) & 1
// 0000 0001 & 1
// 0000 0001
// isSigned := 1

value >>= lo; // move interested bits that they start at 0
// ((0001 1100) >> 2
// 0000 0111
// value := 0000 0111

hi -= lo; // how many bits we want?
// hi := 3

isSigned &= (hi != 0); // hi == 0 <=> hi == lo
// => sign will be always 0
// 1 &= (3 != 0)
// 1
// isSigned := 1

hi -= isSigned; // if the last bit should be sign-bit
// don't evaluate it as value
// hi := 2

result = value & ((1 << hi) - 1); // (1<<hi)-1 creates bit mask
// 0000 0111 & ((1 << 2) - 1)
// 0000 0111 & (100 - 1)
// 0000 0111 & 011
// 0000 0011
// result := 3

if (isSigned) // true
return -result; // return inverted result
// -3
return result; // if false return result
}

int main()
{
assert(0 == getField(0, 0, 0, 0));
assert(0 == getField(0, 0, 0, 1));
assert(0 == getField(15, 0, 0, 0));
assert(0 == getField(15, 0, 0, 1));
assert(0 == getField(15, 1, 1, 0));
assert(0 == getField(15, 3, 3, 1));
assert(0 == getField(0, 3, 0, 0));
assert(0 == getField(0, 4, 0, 1));
// (sign bit)[value bits]
assert(1 == getField(1, 1, 0, 0)); // 000[1]
assert(0 == getField(1, 1, 0, 1)); // 000(1)

assert(3 == getField(15, 2, 0, 0)); // 11[11]
assert(1 == getField(15, 2, 1, 0)); // 11[1]1
assert(7 == getField(15, 4, 1, 0)); // [111]1

assert(2 == getField(5, 4, 1, 0)); // [010]1
assert(2 == getField(5, 3, 1, 0)); // 0[10]1
assert(5 == getField(10, 4, 1, 0)); // [101]0
assert(1 == getField(10, 3, 1, 0)); // 1[01]0

assert(-1 == getField(15, 2, 0, 1)); // 11(1)[1]
assert(0 == getField(15, 2, 1, 1)); // 11(1)1
assert(-3 == getField(15, 4, 1, 1)); // (1)[11]1

assert(2 == getField(5, 4, 1, 1)); // (0)[10]1
assert(0 == getField(5, 3, 1, 1)); // 0(1)[0]1
assert(-1 == getField(10, 4, 1, 1)); // (1)[01]0
assert(1 == getField(10, 3, 1, 1)); // 1(0)[1]0
assert(-2 == getField(12, 4, 1, 1)); // (1)[10]0
assert(-2 == getField(10, 4, 0, 1)); // (1)[010]

assert(-3 == getField(28, 5, 2, 1)); // 000(1) [11]00
}

没有循环。 2 个跳转( (hi != 0)if(isSigned) ),但对我来说, Release模式下的 VCv120 以某种方式处理第一个跳转,所以在代码中我只得到 if() 。我不知道如何摆脱它。

也没有乘法( << - 位移而不是乘法乘以 2),并且只有 4 次减法。不确定哪一个会更快...剩下的一跳...

还有一个时间功能(这次没有注释)

int getField(int value, int hi, int lo, int isSigned) {
int result = 0;
assert(hi >= lo);
isSigned = (value >> (hi-1)) & isSigned;
value >>= lo;
hi -= lo;
isSigned &= (hi != 0);
hi -= isSigned;
result = value & ((1 << hi) - 1);
if (isSigned)
return -result;
return result;
}

编辑

我设法稍微清理了代码:

int getField(int value, int hi, int lo, int isSigned) {
assert(hi >= lo);

hi -= lo;
value >>= lo;
value &= ((1 << hi) - 1);
isSigned <<= (hi - 1);
isSigned &= value;
if (isSigned && (hi != 0)) {
value -= isSigned;
value = ~value + 1;
}
return value;
}

但是生成的asm有2次跳转...

  1. if(已签名
  2. &&(嗨!= 0))

编辑2

在此版本中:

int getField(int value, int hi, int lo, int isSigned) {
assert(hi >= lo);

hi -= lo;
isSigned &= (hi != 0);
value >>= lo;
value &= ((1 << hi) - 1);
isSigned <<= (hi - 1);
isSigned &= value;
if (isSigned) {
value -= isSigned;
value = ~value + 1;
}
return value;
}

只有一次跳跃。

关于c - C 中的 getField 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25828773/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com