简体   繁体   English

如何在 C 中使用有符号或无符号整数进行位映射?

[英]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.

相关问题 C:如何将2 32位无符号整数的结果保存为有符号整数 - C: How to save the result of 2 32 bit unsigned integer into a signed integer C-有符号和无符号整数 - C - Signed and Unsigned integer 如何在32位处理器上使用一个有符号整数和一个无符号整数来生成带符号的64位整数 - How to make signed 64 bit integer using one signed integer and one unsigned integer on 32 bit processor 有符号和无符号,以及C中的位扩展如何工作 - Signed and unsigned, and how bit extension works in C 如何测试有符号或无符号 integer 的最高有效位? - How to test the most significant bit of signed or unsigned integer? c中的3位无符号整数 - 3 bit unsigned integer in c 如何在 C 中创建 24 位无符号 integer - How to create 24 bit unsigned integer in C 如何将有符号整数转换为C中对应的无符号整数? - How to convert a signed integer to a corresponding unsigned integer in C? c 编译器如何处理无符号和有符号整数? 为什么无符号和有符号算术运算的汇编代码相同? - how does c compiler handle unsigned and signed integer? Why the assembly code for unsigned and signed arithmetic operation are the same? 无符号整数位域移位产生有符号整数 - Unsigned integer bit field shift yields signed integer
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM