0

我在 C 中有以下一段代码,我试图从分别存储在val1和中的值中提取特定位val2,然后将提取的位的十进制等效值存储回val1val1val2val2 以供以后比较。nbits给出此处要提取的位范围,例如从 2 到 2,这意味着只提取第三位。

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];

上面这段代码在 32 位机器上可以正常工作,但在 64 位机器上会给出错误的结果,特别是当存储在val1和中的初始值val2是负数时。我必须对上面的代码进行哪些更改才能使其独立于机器?

4

4 回答 4

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 移位而不是使用表。IE

mask_val = mask_val| ( 0x1 << (i - 1) );
于 2012-06-27T18:41:05.427 回答
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");
}
于 2012-06-27T18:50:19.857 回答
0

代码仍在按原样工作,但我怀疑您的符号位高于 32 位标记。请参考这篇文章,如果它有帮助,请告诉我: 64 位 Windows 上 long 的位大小是多少?

于 2012-06-27T18:25:30.280 回答
0

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

于 2012-06-27T18:28:11.733 回答