[英]How to use signed or unsigned integer for bit mapping in C?
I want to reset the 31st bit (last bit, 0 to 31 range) of int32_t, only this case seems to fail.我想重置 int32_t 的第 31 位(最后一位,0 到 31 范围),只有这种情况似乎失败了。 ie, Output failed for the case when 'i' is 31, it's returning -1.即,当“i”为 31 时,输出失败,返回 -1。 What is the error and how do I resolve this?这是什么错误,我该如何解决?
#include <stdio.h>
#include <stdlib.h>
void Release(int ResetBit, int32_t *Val)
{
int32_t testBit = 1; /* XoR Bit */
if (ResetBit >= 0 && ResetBit < 32)
{
testBit = (testBit << ResetBit);
*Val ^= testBit;
}
else
{
perror("Max range is 0-31 only, failed! ");
//exit(1);
}
}
int main(int argc, char const *argv[])
{
int count = 0;
for (int i = 0; i < 32; i++)
{
int32_t MaxValue = 2147483647;
Release(i, &MaxValue);
printf("MaxValue = %d NodeID = % d\n", MaxValue, i);
count++;
}
printf("%d", count);
return 0;
}
Output for the case i = 31 is:情况 i = 31 的输出是:
MaxValue = -1 NodeID = 31 MaxValue = -1 NodeID = 31
First of all: Don't use signed integers for bitmaps.首先:不要对位图使用有符号整数。 Always use unsigned .始终使用unsigned 。 The reason for that is that bit shifting on signed integers may result in undefined behavior while shifting unsigned integers are always safe.这样做的原因是有符号整数的位移可能导致未定义的行为,而无符号整数的位移总是安全的。
Secondly: You are using XOR in the Release
function.其次:您在Release
函数中使用 XOR。 XOR with testBit
will not clear a bit.与testBit
异或不会清除一点。 XOR will toggle the bit value, ie 1 becomes 0 and 0 becomes 1. Instead you want: *Val &= ~testBit;
XOR 将切换位值,即 1 变为 0,0 变为 1。相反,您需要: *Val &= ~testBit;
It works like:它的工作原理如下:
If testBit is 0000.0000.0000.0000.0000.0000.0000.1000
then ~testbit is 1111.1111.1111.1111.1111.1111.1111.0111
then *Val &= ... will clear bit number 3 and keep all other unchanged
as `&` is a bitwise AND operation.
When using unsigned remember to change the printf
to print an unsigned instead of using %d
, ie like printf("%" PRIu32 "\\n", uint32t_variable);
使用 unsigned 时,请记住将printf
更改为打印 unsigned 而不是使用%d
,即像printf("%" PRIu32 "\\n", uint32t_variable);
. .
EDIT编辑
What went wrong with the XOR? XOR 出了什么问题?
Let's assume that you are using uint32_t
and XOR, then this will happen:让我们假设您正在使用uint32_t
和 XOR,那么这将发生:
Your input is您的输入是
0111.1111.1111.1111.1111.1111.1111.1111
and you XOR with而你与
1000.0000.0000.0000.0000.0000.0000.0000
which toggles bit 31 resulting in切换位 31 导致
1111.1111.1111.1111.1111.1111.1111.1111
The function was supposed to clear bit 31 but it didn't.该函数应该清除第 31 位,但它没有。 XOR is just not the correct operator for that. XOR 不是正确的运算符。
If you don't need an actual signed type, use uint32_t
and all problems will go away.如果您不需要实际的签名类型,请使用uint32_t
并且所有问题都会消失。 The problem with using bitwise operators on signed types is various forms of poorly-defined behavior.在有符号类型上使用按位运算符的问题是各种形式的定义不明确的行为。
For example, left-shifting something into the sign bit of a int32_t
leads to undefined behavior, meaning a potential bug in case your compiler doesn't cover that case with a non-standard extension.例如,将某些内容左移到int32_t
的符号位会导致未定义的行为,这意味着一个潜在的错误,以防您的编译器没有使用非标准扩展覆盖这种情况。 Similarly, right-shifting a negative number can either lead to arithmetic or logic shift, the C standard doesn't specify which one, but allows both forms.类似地,右移负数可以导致算术或逻辑移位,C 标准没有指定哪一种,但允许两种形式。
That being said, if you simply wish to set/clear bit 31 of an int32_t
, it's well-defined to do so like this:话虽如此,如果您只是想设置/清除int32_t
31 位,那么这样做是明确定义的:
int32_t i32 = ...;
i32 |= 1u << 31; // set MSB
i32 &= ~(1u << 31); // clear MSB
i32 ^= 1u << 31; // toggle MSB
Where the u
is ensuring unsigned arithmetic.其中u
确保无符号算术。
Use the correct bitwise operation.使用正确的按位运算。 to reset bit use &
重置位使用&
int32_t ResetBit(int bit, int32_t *val)
{
uint32_t mask = ~(1UL << bit);
*val &= mask;
return *val;
}
and usage:和用法:
void printnitd(int32_t val)
{
for(uint32_t mask = 1UL << 31; mask; mask >>= 1)
{
printf("%c", (val & mask) ? '1' : '0');
}
}
int main(void)
{
for(int bit = 0; bit < 32; bit++)
{
int32_t a = -1;
printf("bit %u = ", a);
printnitd(ResetBit(bit, &a));
printf("\n");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.