2

我正在学习 C,我仍然是一个非常初学者。

我的问题如下。我有一个 unsigned int x 和一个 unsigned int y。我想将 n 位从位置 p 从 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;
}

但它不起作用:

在 28 到 32 的位置 3 放置 2 位的结果是 402653216

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

非常感谢

4

5 回答 5

2

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

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

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

在此处输入图像描述

看起来您是从目标号码的错误端进行操作。将您的逻辑更改为从右侧 (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);

在此处输入图像描述

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

在此处输入图像描述

于 2013-11-03T17:17:31.663 回答
2

你把面具弄错了。尝试:

unsigned mask = ((1 << n) - 1) << p;
return (y & ~mask) | (x & mask);
于 2013-11-03T17:44:13.763 回答
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));

}

于 2014-03-29T03:37:51.653 回答
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]

于 2013-11-05T21:06:50.173 回答
0
unsigned char
copy_Nbits(unsigned char num_S, unsigned char num_D, char start_off, char end_off)
{
    unsigned char u1 = 0;
    unsigned char u2 = 0;

    u1 = ~u1;
    u1 = (u1 >> ((8 * sizeof(num_S)) - 1 - end_off + start_off));
    u1 = (u1 << start_off);
    u2 = u1;
    u2 &= num_S;

    u1 = ~u1;
    u1 &= num_D;

    return (u1 | u2);
}
于 2017-05-27T22:35:18.727 回答