将给定位置的n位复制到C中的x到y

时间:2013-11-03 16:46:48

标签: c bit-manipulation

我正在学习C,而且我还是一个非常初学者。

我的问题如下。我有一个unisgned int x和一个unsigned int y。我想将位置p中的n位从x复制到y上的相同位置。我发现了一些类似的问题,但在C中却没有,大多数情况下,如果最右边或最左边的位,问题会略有不同。我还想找到一种不依赖于机器上的整数表示的解决方案。

这就是我做的事情

unsigned fix_bits(unsigned x, unsigned y, int n, int p)
{
    unsigned u1,u2,u3,u4,x1,y1,yf;
    u1 = ~0; /*vector of 1*/
    u2 = (u1>>n); /*0 from 0 to n-1 and 1s*/
    u3 = ~(u2);/*1 from 0 to n-1 and 0s*/
    u4 = u3>>p;/*0 from 0 to p-1, n 1 from p to p+n+1 and 0s*/
    x1 = (x & u4);/*only keep n bits of x from position p*/
    y1 = (y | u4);/*set y bit  from p to (p+n+1) to 1, rest remains unchanged (0 | bit = bit)*/
    yf = (x1 | y1);
    return yf;
}

但它不起作用:

将2位置于28至32位置3的结果为402653216

有人知道我做错了什么吗?

非常感谢

5 个答案:

答案 0 :(得分:2)

关于问题: 将位置p中的n位从x复制到y上的相同位置

您的代码与OP中的结果一样:

unsigned int x = 0xffffffff;
unsigned int y = 0x00000000;
unsigned int z = 0x00000000;
z = fix_bits(x, y, 5, 5);    

enter image description here

看起来你正在从目标号码的错误一端开始操作。将您的逻辑更改为从右侧(LSB)而不是左侧(MSB)。

试试这个:

unsigned fix_bits(unsigned x, unsigned y, int n, int p)
{
    unsigned a, b, c, d, e;
    int mask;
    //Get mask
    mask = ((1<<(n))-1)<<(p-n); //[edit] corrected, was ...<<p, is ...<<(p-n)
    //apply mask to destination, 
    //XOR that with repositioned, BITwise NOTed source and apply mask
    /*so you can do these steps:
    a = mask|y;
    b = ~x;
    c = b<<p;
    d = c&mask;
    e = d^a;

    return e;*/
    //or do this one:  
    return ((mask&(~x<<p))^(mask|y)); //same thing
}  

对于显示的输入,示例输出如下:

unsigned int x = 0xffffffff;
unsigned int y = 0xf0000000;
unsigned int z = 0x00000000;

z = fix_bits(x, y, 3, 20);

enter image description here

修正掩码后的结果( <<p <<(p-n) ):

enter image description here

答案 1 :(得分:2)

你的面具错了。尝试:

unsigned mask = ((1 << n) - 1) << p;
return (y & ~mask) | (x & mask);

答案 2 :(得分:0)

所以我的最终解决方案就是

unsigned fix_bits(unsigned x, unsigned y, int n, int p)

{

    unsigned u1,u2,u3,u4,x1,y1,yf;
    u1 = ~0; /*vector of 1*/
    u2 = (u1<<n); /*0 from 0 to n-1 and 1s*/
    u3 = ~(u2);/*1 from 0 to n-1 and 0s*/
    u4 = u3<<p;/*0 from 0 to p-1, n 1 from p to p+n+1 and 0s*/
    x1 = (x & u4);/*only keep n bits of x from position p*/
    y1 = (y | u4);/*set y bit  from p to (p+n+1) to 1, rest remains unchanged (0 | bit = bit)*/
    yf = (x1 | y1);
    return yf;

}

然后

x = 28 = [0 0 ... 0 1 1 1 0]

y = 32 = [0 0 ... 1 0 0 0 0]

fix_bits(28,32,2,3)/ 将位置3的两位从28位置放到32位 /

输出

z = 56 = [0 0 ... 1 1 1 0 0]

答案 3 :(得分:0)

我需要一个类似的功能来构建NES模拟器。使用@ryyker的解决方案,我为uint16_t创建了一个稍微更通用的函数。它可能会被优化。在source_pos = dest_pos时,它还应符合原始海报的要求。

也许有人在寻求解决一般情况时带到这里会发现这很有帮助。

/*                                                                                                                                                                  
 * This was fun to figure out.  Copy num bits at source_pos from source
 * into dest at dest_pos.  Positions start at 0, the LSB.
 */
uint16_t set_bits(uint16_t source, uint16_t dest, int num, int source_pos, int dest_pos)                                                                            
{
    unsigned long mask = ((1UL<<(num))-1UL)<<(source_pos);

    if (dest_pos >= source_pos) {
            return (dest & (~(mask << dest_pos))) | ((source & mask) << dest_pos);
    }

    return (dest & (~(mask >> (source_pos - dest_pos)))) | ((source & mask) >> (source_pos - dest_pos));

}

答案 4 :(得分:0)

(env) jsnyder10@jsnyder10-VirtualBox:~/Documents/45$ flask/bin/python manage.py alchemydumps create
Traceback (most recent call last):
  File "manage.py", line 36, in <module>
    manager.run()
  File "/home/jsnyder10/Documents/45/flask/local/lib/python2.7/site-packages/flask_script/__init__.py", line 412, in run
    result = self.handle(sys.argv[0], sys.argv[1:])
  File "/home/jsnyder10/Documents/45/flask/local/lib/python2.7/site-packages/flask_script/__init__.py", line 383, in handle
    res = handle(*args, **config)
  File "/home/jsnyder10/Documents/45/flask/local/lib/python2.7/site-packages/flask_script/commands.py", line 216, in __call__
    return self.run(*args, **kwargs)
  File "/home/jsnyder10/Documents/45/flask/local/lib/python2.7/site-packages/flask_alchemydumps/__init__.py", line 48, in create
    data = alchemy.get_data()
  File "/home/jsnyder10/Documents/45/flask/local/lib/python2.7/site-packages/flask_alchemydumps/helpers/database.py", line 36, in get_data
    query = db.session.query(model)
  File "/home/jsnyder10/Documents/45/flask/local/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 157, in do
    return getattr(self.registry(), name)(*args, **kwargs)
  File "/home/jsnyder10/Documents/45/flask/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1330, in query
    return self._query_cls(entities, self, **kwargs)
  File "/home/jsnyder10/Documents/45/flask/local/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 139, in __init__
    self._set_entities(entities)
  File "/home/jsnyder10/Documents/45/flask/local/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 148, in _set_entities
    entity_wrapper(self, ent)
  File "/home/jsnyder10/Documents/45/flask/local/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 3971, in __init__
    "expected - got '%r'" % (column, )
sqlalchemy.exc.InvalidRequestError: SQL expression, column, or mapped entity expected - got '<class 'flask_sqlalchemy.Model'>'