32位和64位机器中的位操作

时间:2012-06-27 18:16:25

标签: c 64-bit bit-manipulation 32bit-64bit bitwise-operators

我在C中有以下代码,我试图分别从val1val2中存储的值中提取特定位,然后将提取位的十进制等值存储回{{1和} val1以便稍后比较val1和val2。 val2给出了这里要提取的比特范围,例如从2到2,这意味着只提取第三个比特。

nbits

上面的这段代码适用于32位机器,但是对于64位机器,特别是当static unsigned int BIT[] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000 }; int val1, val2; unsigned long mask_val; int nbits[2]; nbits[0] = nbits[1] = 2; val1 = -41; val2 = -45; for (i = nbits[0]; i <= nbits[1]; i++) mask_val = mask_val|BIT[i]; val1 = (val1 & mask_val) >> nbits[0]; val2 = (val2 & mask_val) >> nbits[0]; val1中存储的初始值为负时,会给出错误的结果。我需要对上面的代码进行哪些更改才能使其与机器无关?

4 个答案:

答案 0 :(得分:3)

1,不初始化mask_val会导致许多编译器出现问题 2,使用stdint.h,它的vals和mask的类型是独立于系统的

int8_t
int16_t
int32_t
uint8_t
uint16_t
uint32_t
int64_t
uint64_t

3,为什么不从0x1进行bitshift而不是使用表。即

mask_val = mask_val| ( 0x1 << (i - 1) );

答案 1 :(得分:1)

当我开发各种版本的代码时,其他人基本上都说明了我在下面显示的相同内容。

我认为你的代码在32位版本上工作的原因是侥幸;显然在那个系统上你的未初始化的mask_val恰好是零,你是“幸运的”。

下面我展示了您自己代码的三个版本的进展。首先显示代码基本不变,但是将mask_val初始化为0,并将typedef用于您希望代码运行的任何类型。第二个是相同的,但没有BIT []表。第三,消除了循环。

#if 0
#include <stdio.h>

typedef long long valTy;

int main()
{
static unsigned int BIT[] = {
0x1,        0x2,        0x4,        0x8,
0x10,       0x20,       0x40,       0x80,
0x100,      0x200,      0x400,      0x800,
0x1000,     0x2000,     0x4000,     0x8000,
0x10000,    0x20000,    0x40000,    0x80000,
0x100000,   0x200000,   0x400000,   0x800000,
0x1000000,  0x2000000,  0x4000000,  0x8000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000
};
valTy val1, val2;
valTy mask_val;
int i, nbits[2];

printf("\n");

nbits[0] = nbits[1] = 2;
val1 = -41;
val2 = -45;

printf("    val1 = 0x%016llx (%lld)\n", (long long)val1, (long long)val1);
printf("    val2 = 0x%016llx (%lld)\n", (long long)val2, (long long)val2);
printf("\n");

mask_val = 0;
for (i = nbits[0]; i <= nbits[1]; i++)
    mask_val = mask_val|BIT[i];
printf("mask_val = 0x%016llx\n\n", (long long)mask_val);
val1 = (val1 & mask_val) >> nbits[0];
val2 = (val2 & mask_val) >> nbits[0];

printf("    val1 = 0x%016llx (%lld)\n", (long long)val1, (long long)val1);
printf("    val2 = 0x%016llx (%lld)\n", (long long)val2, (long long)val2);
printf("\n");
}

#endif




#if 0
#include <stdio.h>

typedef long long valTy;
#define BIT(bitnum) (1<<bitnum)

int main()
{
valTy val1, val2;
valTy mask_val;
int i, nbits[2];

printf("\n");

nbits[0] = nbits[1] = 2;
val1 = -41;
val2 = -45;

printf("    val1 = 0x%016llx (%lld)\n", (long long)val1, (long long)val1);
printf("    val2 = 0x%016llx (%lld)\n", (long long)val2, (long long)val2);
printf("\n");

mask_val = 0;
for (i = nbits[0]; i <= nbits[1]; i++)
    mask_val = mask_val | BIT(i);
printf("mask_val = 0x%016llx\n\n", (long long)mask_val);
val1 = (val1 & mask_val) >> nbits[0];
val2 = (val2 & mask_val) >> nbits[0];

printf("    val1 = 0x%016llx (%lld)\n", (long long)val1, (long long)val1);
printf("    val2 = 0x%016llx (%lld)\n", (long long)val2, (long long)val2);
printf("\n");
}

#endif

#include <stdio.h>

typedef long long valTy;
#define BIT(bitnum) (1<<bitnum)

int main()
{
valTy val1, val2;
valTy mask_val;
int i, nbits[2];

printf("\n");

nbits[0] = nbits[1] = 2;
val1 = -41;
val2 = -45;

printf("    val1 = 0x%016llx (%lld)\n", (long long)val1, (long long)val1);
printf("    val2 = 0x%016llx (%lld)\n", (long long)val2, (long long)val2);
printf("\n");

mask_val = 0;
{
    valTy maskTop = ((BIT(nbits[0])-1)<<1)|1;
    valTy maskBottom = BIT(nbits[1])-1;
    mask_val = maskTop & ~maskBottom;
}
printf("mask_val = 0x%016llx\n\n", (long long)mask_val);
val1 = (val1 & mask_val) >> nbits[0];
val2 = (val2 & mask_val) >> nbits[0];

printf("    val1 = 0x%016llx (%lld)\n", (long long)val1, (long long)val1);
printf("    val2 = 0x%016llx (%lld)\n", (long long)val2, (long long)val2);
printf("\n");
}

答案 2 :(得分:0)

代码仍然按照写入的方式工作,但我怀疑你的符号位高于32位标记。请参阅这篇文章,如果有帮助请告诉我: What is the bit size of long on 64-bit Windows?

答案 3 :(得分:0)

我认为您的问题来自mask_val未初始化的事实。你应该用0初始化它,以确保在循环开始之前没有设置位。