如何使用 uint64_t 数据类型在 C 中实现位图数组?
How to implement bitmap array in C using uint64_t data type?
我正在尝试在 C 中实现位图数组。
我已阅读并复制粘贴此 link:What is a bitmap in C?
#include <limits.h> /* for CHAR_BIT */
#include <stdint.h> /* for uint32_t */
#include <stdio.h>
#include <stdlib.h>
typedef uint32_t word_t; // I want to change this, from uint32_t to uint64_t
enum { BITS_PER_WORD = sizeof(word_t) * CHAR_BIT };
#define WORD_OFFSET(b) ((b) / BITS_PER_WORD)
#define BIT_OFFSET(b) ((b) % BITS_PER_WORD)
void set_bit(word_t *words, int n) {
words[WORD_OFFSET(n)] |= (1 << BIT_OFFSET(n));
}
void clear_bit(word_t *words, int n) {
words[WORD_OFFSET(n)] &= ~(1 << BIT_OFFSET(n));
}
int get_bit(word_t *words, int n) {
word_t bit = words[WORD_OFFSET(n)] & (1 << BIT_OFFSET(n));
return bit != 0;
}
int main(){
printf("sizeof(word_t)=%i\n",sizeof(word_t));
printf("CHAR_BIT=%i\n",CHAR_BIT);
printf("BITS_PER_WORD=%i\n",BITS_PER_WORD);
word_t x;
set_bit(&x, 0);
printf("x=%u\n",x);
set_bit(&x, 1);
printf("x=%u\n",x);
set_bit(&x, 2);
printf("x=%u\n",x);
return 0;
}
使用uint32_t,代码运行良好。它打印 x 值:1、3 和 7,分别像这样:
[izzatul@mycomputer latihan]$ ./a.out
sizeof(word_t)=8
CHAR_BIT=8
BITS_PER_WORD=64
x=1
x=3
x=7
没用。 x 值变为 1295807169 等,这出乎我的意料。我希望它和以前一样(1、3、7)。有人可以帮我修复该代码吗?
我知道“<<”是位移位,就是把位向左移动(或者向右加0)。
但是我还是不知道怎么自己修改代码。
问题在于代码使用了 1
整数常量。所有此类整数常量都具有与变量一样的类型,并且默认为 int
,这可能与您系统上的 int32_t
相同。
将像 int32_t
这样的有符号整数左移 30 位以上会调用未定义的行为,因为您会将数据移入符号位。根据经验,切勿将带符号变量与按位运算符一起使用。
这种情况下的正确解决方法是将 1 << BIT_OFFSET(n)
的每个实例替换为:
(word_t)1 << BIT_OFFSET(n)
或者使用 1ull
后缀,但这可能会在较小的系统上产生不必要的缓慢代码。
请注意,printf 的正确格式说明符是 inttypes.h 中的 printf("x=%"PRIu64 "\n",x);
。
我正在尝试在 C 中实现位图数组。 我已阅读并复制粘贴此 link:What is a bitmap in C?
#include <limits.h> /* for CHAR_BIT */
#include <stdint.h> /* for uint32_t */
#include <stdio.h>
#include <stdlib.h>
typedef uint32_t word_t; // I want to change this, from uint32_t to uint64_t
enum { BITS_PER_WORD = sizeof(word_t) * CHAR_BIT };
#define WORD_OFFSET(b) ((b) / BITS_PER_WORD)
#define BIT_OFFSET(b) ((b) % BITS_PER_WORD)
void set_bit(word_t *words, int n) {
words[WORD_OFFSET(n)] |= (1 << BIT_OFFSET(n));
}
void clear_bit(word_t *words, int n) {
words[WORD_OFFSET(n)] &= ~(1 << BIT_OFFSET(n));
}
int get_bit(word_t *words, int n) {
word_t bit = words[WORD_OFFSET(n)] & (1 << BIT_OFFSET(n));
return bit != 0;
}
int main(){
printf("sizeof(word_t)=%i\n",sizeof(word_t));
printf("CHAR_BIT=%i\n",CHAR_BIT);
printf("BITS_PER_WORD=%i\n",BITS_PER_WORD);
word_t x;
set_bit(&x, 0);
printf("x=%u\n",x);
set_bit(&x, 1);
printf("x=%u\n",x);
set_bit(&x, 2);
printf("x=%u\n",x);
return 0;
}
使用uint32_t,代码运行良好。它打印 x 值:1、3 和 7,分别像这样:
[izzatul@mycomputer latihan]$ ./a.out
sizeof(word_t)=8
CHAR_BIT=8
BITS_PER_WORD=64
x=1
x=3
x=7
没用。 x 值变为 1295807169 等,这出乎我的意料。我希望它和以前一样(1、3、7)。有人可以帮我修复该代码吗?
我知道“<<”是位移位,就是把位向左移动(或者向右加0)。 但是我还是不知道怎么自己修改代码。
问题在于代码使用了 1
整数常量。所有此类整数常量都具有与变量一样的类型,并且默认为 int
,这可能与您系统上的 int32_t
相同。
将像 int32_t
这样的有符号整数左移 30 位以上会调用未定义的行为,因为您会将数据移入符号位。根据经验,切勿将带符号变量与按位运算符一起使用。
这种情况下的正确解决方法是将 1 << BIT_OFFSET(n)
的每个实例替换为:
(word_t)1 << BIT_OFFSET(n)
或者使用 1ull
后缀,但这可能会在较小的系统上产生不必要的缓慢代码。
请注意,printf 的正确格式说明符是 inttypes.h 中的 printf("x=%"PRIu64 "\n",x);
。