简体   繁体   English

在 C 中实现按位运算

[英]Implementing bitwise operations in C

I am trying to implement two bitwise functions in C:我正在尝试在 C 中实现两个按位函数:

set(unsigned *x, unsigned n, unsigned v) --> Sets the nth bit of the value x to the value v. V is either 0 or 1, and N is [0, 31] for simplicities sake. set(unsigned *x, unsigned n, unsigned v) --> 将值 x 的第 n 位设置为值 v。V 是 0 或 1,为了简单起见,N 是 [0, 31]。

flip(unsigned *x, unsigned n) --> Flips the Nth bit in x. flip(unsigned *x, unsigned n) --> 翻转 x 中的第 N 位。 Assume N is [0,31] for simplicities sake.为简单起见,假设 N 为 [0,31]。

My implementation:我的实现:


void set(unsigned *x, unsigned n, unsigned v) {
 
    *x = (1 << n) | v;
    
}


void flip(unsigned *x, unsigned n) {
    
    *x = n ^ (1 << *x);

}

My problem: The functions don't work logically.我的问题:这些功能不符合逻辑。

The output from test cases:测试用例的输出:

Testing set_bit()测试 set_bit()

set_bit(0x0000004e,2,0) returned 0x00000004 but we expected 0x0000004a set_bit(0x0000006d,0,0) returned 0x00000001 but we expected 0x0000006c set_bit(0x0000004e,2,1) returned 0x00000005 but we expected 0x0000004e set_bit(0x0000006d,0,1) returned 0x00000001 but we expected 0x0000006d set_bit(0x0000004e,9,0) returned 0x00000200 but we expected 0x0000004e set_bit(0x0000006d,4,0) returned 0x00000010 but we expected 0x0000006d set_bit(0x0000004e,9,1) returned 0x00000201 but we expected 0x0000024e set_bit(0x0000006d,7,1) returned 0x00000081 but we expected 0x000000ed SET_BIT(0x0000004e,2,0)返回0x00000004,但我们预计0x0000004a SET_BIT(0x0000006d,0,0)返回00000001,但我们预计0x0000006c SET_BIT(0x0000004e,2,1)返回0x00000005,但我们预计0x0000004e SET_BIT(0x0000006d,0,1)返回00000001但我们预计0x0000006d SET_BIT(0x0000004e,9,0)返回0x00000200,但我们预计0x0000004e SET_BIT(0x0000006d,4,0)返回0x00000010,但我们预计0x0000006d SET_BIT(0x0000004e,9,1)返回0x00000201,但我们预计0x0000024e SET_BIT( 0x0000006d,7,1) 返回 0x00000081 但我们期望 0x000000ed

Testing flip_bit()测试 flip_bit()

flip_bit(0x0000004e,0) returned 0x00004000, but we expected 0x0000004f flip_bit(0x0000004e,1) returned 0x00004001, but we expected 0x0000004c flip_bit(0x0000004e,2) returned 0x00004002, but we expected 0x0000004a flip_bit(0x0000004e,5) returned 0x00004005, but we expected 0x0000006e flip_bit(0x0000004e,9) returned 0x00004009, but we expected 0x0000024e flip_bit(0x0000004e,0)返回0x00004000,但我们预期0x0000004f flip_bit(0x0000004e,1)返回0x00004001,但我们预期0x0000004c flip_bit(0x0000004e,2)返回0x00004002,但我们预期0x0000004a flip_bit(0x0000004e,5)返回0x00004005,但我们预期 0x0000006e flip_bit(0x0000004e,9) 返回 0x00004009,但我们预期 0x0000024e

You should give the variables more meaningful names than 1 character ones that has to be explained with comments.您应该为变量提供比必须用注释解释的 1 个字符更有意义的名称。

We should never use signed numbers when doing bitwise operations and 1 is signed int.在进行按位运算时,我们永远不应该使用有符号数字,并且1是有符号整数。 So 1<<31 is a bug.所以1<<31是一个错误。

Also, your function set cannot be used for setting a bit to value 0 since bitwise OR doesn't work that way.此外,您的函数集不能用于将位设置为值 0,因为按位 OR 不能那样工作。 You either need separate functions for setting/clearing, or you need to include a branching if statement inside the function, example:您要么需要单独的函数来设置/清除,要么需要在函数内部包含一个分支if语句,例如:

if(bit_value) 
  *value |= 1u<<n;
else
  *value &= ~(1u<<n);

A more sensible interface that can be used with any type, is to use an array of characters.可用于任何类型的更合理的接口是使用字符数组。 Then you can pass along a pointer to integer, cast it, and it is guaranteed to work.然后你可以传递一个指向整数的指针,转换它,它保证工作。

void bit_set (unsigned char* data, size_t byte, unsigned char bit)
{
  data[byte] |= 1u << bit;
}

void bit_clear (unsigned char* data, size_t byte, unsigned char bit)
{
  data[byte] &= ~(1u << bit);
}

void bit_toggle (unsigned char* data, size_t byte, unsigned char bit)
{
  data[byte] ^= 1u << bit; 
}

If we logically follow through with your code, we can see what is happening.如果我们在逻辑上遵循您的代码,我们可以看到发生了什么。 Let's use your first example with input 0x4e and output 0x04.让我们使用输入 0x4e 和输出 0x04 的第一个示例。 I'm only going to look at one byte for simplicity's sake.为简单起见,我只看一个字节。

First, you bitshift 1 over N amount of times.首先,您将 1 移位 N 次。 In this case, N = 2. In binary, that looks like this:在这种情况下,N = 2。在二进制中,它看起来像这样:

value    : N
---------:--
00000001 : 0
00000010 : 1
00000100 : 2

next, we bitwise-or that value with V where V = 0:接下来,我们用 V 来按位或该值,其中 V = 0:

00000100 | 00000000 => 00000100

and last, that value gets assigned to the value at the address X. In binary, the value 00000100 is equivalent to 0x04 in hexadecimal which matches your actual output.最后,该值被分配给地址 X 处的值。在二进制中,值 00000100 相当于十六进制的 0x04,与您的实际输出相匹配。

Now that we have identified the logical error, we can propose appropriate instructions to get you where you want to be.现在我们已经确定了逻辑错误,我们可以提出适当的说明,让您到达您想要的位置。 I propose the following (though there may be other ways that are better).我提出以下建议(尽管可能还有其他更好的方法)。

void set_bit(unsigned *x, unsigned n, unsigned v) {
 
    unsigned temp = (1 << n);
    *x = v ? *x | temp : *x & ~temp;
    
}

What is happening here is first we are storing the value calculated by the bitshift: 00000100. Then we are choosing to do one of two instructions based on the value of V.这里发生的事情是首先我们存储由位移计算的值:00000100。然后我们选择根据 V 的值执行两条指令之一。

if v == 1
    X        : TEMP                 : HEX
    01001110 | 00000100 => 01001110 : 0x4e
if v == 0
    X        : ~TEMP                 : HEX
    01001110 & 11111011 => 01001010 : 0x4a

This should get you to your desired output when V = 0.当 V = 0 时,这应该可以让您获得所需的输出。

The other function is actually much simpler.另一个函数实际上要简单得多。 We can do a bitwise-exclusive-or:我们可以做一个按位异或:

void flip_bit(unsigned *x, unsigned n) {
    
    unsigned temp = (1 << n);
    *x ^= temp;

}

And this is how it looks in binary when N = 0:这是当 N = 0 时它在二进制中的样子:

X        : TEMP                 : HEX
01001110 ^ 00000001 => 01001111 : 0x4f

Again, that matches your expected output.同样,这符合您的预期输出。

If any of this is confusing, a simple google search of how bitwise operators work should provide insight.如果其中任何一个令人困惑,那么对按位运算符如何工作的简单谷歌搜索应该可以提供见解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM