如何 set/flip C 中的位域
How to set/flip bitfields in C
我正在尝试将 uint64_t
位域全部设置为 0。然后当我在给定字符串中调用该函数时,它与我设置的静态全局数组匹配,它将翻转位为 1。目前我有以下代码,但由于某种原因,当给它不同的字符串时,它遵循相同的行为。因此,例如,当我输入以下 "ABC" 字符串时,它应该打印出 111000
。我将如何获得以下行为。
const size_t SETSIZE = sizeof(uint64_t) << 3;
char key[5] = { 'A', 'B', 'C', 'D', 'E', 'F' }
uint64_t set_encode(char *st) {
int i, j;
uint64_t set = 0;
int length = strlen(st);
for (i = 0; i < length; i++) {
for (j = 0; j < 5; j++) {
if (st[i] == key[j]) {
printf("%c", st[0]);
set = set | 1 << (SETSIZE - 1 - i);
}
}
}
printf("%lu\n", set);
return set;
}
Or-ing 编码为 int
而不是希望的 uint64_t
1 <<(SETSIZE-1-i)
结果类型 int
。此外,可能是 UB,因为某些班次计数肯定比 int
.
宽
// set = set| 1 <<(SETSIZE-1-i);
set |= ((uint64_t) 1) <<(SETSIZE-1-i);
有问题的打印说明符。 "%lu"
可能不会闩锁 uint64_t
.
#include <inttypes.h>
// printf("%lu\n",set);
printf("%" PRIu64 "\n", set);
// Perhaps print as hexadecimal makes more sense
printf("%" PRIX64 "\n", set);
注意 key[]
太小了。
// char key[5] = {'A','B','C','D','E','F'}
char key[5+1] = {'A','B','C','D','E','F'}
// or
char key[] = {'A','B','C','D','E','F'}
以及为什么打印 st[0]
// printf("%c",st[0]);
printf("%c",st[i]);
即使进行了修复,OP 的最终目标也不明确也无法实现。
您的代码中存在多个问题:
const size_t SETSIZE = sizeof(uint64_t) << 3;
字节可能不是 8 位,您应该使用 const size_t SETSIZE = 64;
,因为 uint64_t
类型(如果存在)被定义为恰好 64 位宽,并具有 2 的补码表示形式。
char key[5] = { 'A', 'B', 'C', 'D', 'E', 'F' }
初始化器有 6 个字符,但显式大小设置为 5
。使用 char key[] = { 'A', 'B', 'C', 'D', 'E', 'F' };
。请注意 key
不是 C 字符串,因为初始值设定项中不存在 '[=26=]'
。另请注意,初始化程序末尾缺少 ;
。
uint64_t set_encode(char *st) {
你不修改st
指向的字符串,使用const char *st
int i, j;
i
和 j
应定义为 size_t
以与 length
.
保持一致
uint64_t set = 0;
int length = strlen(st);
return类型为size_t
,因为字符串的长度可能大于int
的范围。在您的特定情况下,它不是基础函数,因为该函数仅对最多 64 个字符的字符串有用,您还应该对此进行测试。
for (i = 0; i < length; i++) {
for (j = 0; j < 5; j++) {
j
应与 sizeof(key)
.
进行比较
if (st[i] == key[j]) {
printf("%c", st[0]);
您可能想要打印 st[i]
而不是 st[0]
。
set = set | 1 << (SETSIZE - 1 - i);
使用从最低值到最高值的位可能更一致,并且 1
必须转换为 (uint64_t)
以避免 int
上的算术溢出超过 31 个字符的字符串(如果 int
是 32 位宽):set = set | (uint64_t)1 << i;
。但是请注意,即使进行转换,对于大于 63 或负数的移位量,移位操作仍未定义。
}
}
}
printf("%lu\n", set);
set
不一定是 long
。您可以将其打印为至少 64 位宽的 unsigned long long
:printf("%llu\n", (unsigned long long)set);
或者您可以使用 <inttypes.h>
中的格式说明符:printf("%"PRIu64"\n", set);
return set;
}
这是更正后的版本:
const size_t SETSIZE = 64;
char key[] = { 'A', 'B', 'C', 'D', 'E', 'F' };
uint64_t set_encode(const char *st) {
uint64_t set = 0;
size_t length = strlen(st);
if (length > SETSIZE) {
printf("string too long: %zd bytes\n", length);
length = SETSIZE;
}
for (size_t i = 0; i < length; i++) {
for (size_t j = 0; j < sizeof(key); j++) {
if (st[i] == key[j]) {
printf("%c", st[i]);
set |= (uint64_t)1 << i;
}
}
}
printf("%llu\n", (unsigned long long)set);
return set;
}
我正在尝试将 uint64_t
位域全部设置为 0。然后当我在给定字符串中调用该函数时,它与我设置的静态全局数组匹配,它将翻转位为 1。目前我有以下代码,但由于某种原因,当给它不同的字符串时,它遵循相同的行为。因此,例如,当我输入以下 "ABC" 字符串时,它应该打印出 111000
。我将如何获得以下行为。
const size_t SETSIZE = sizeof(uint64_t) << 3;
char key[5] = { 'A', 'B', 'C', 'D', 'E', 'F' }
uint64_t set_encode(char *st) {
int i, j;
uint64_t set = 0;
int length = strlen(st);
for (i = 0; i < length; i++) {
for (j = 0; j < 5; j++) {
if (st[i] == key[j]) {
printf("%c", st[0]);
set = set | 1 << (SETSIZE - 1 - i);
}
}
}
printf("%lu\n", set);
return set;
}
Or-ing 编码为 int
而不是希望的 uint64_t
1 <<(SETSIZE-1-i)
结果类型 int
。此外,可能是 UB,因为某些班次计数肯定比 int
.
// set = set| 1 <<(SETSIZE-1-i);
set |= ((uint64_t) 1) <<(SETSIZE-1-i);
有问题的打印说明符。 "%lu"
可能不会闩锁 uint64_t
.
#include <inttypes.h>
// printf("%lu\n",set);
printf("%" PRIu64 "\n", set);
// Perhaps print as hexadecimal makes more sense
printf("%" PRIX64 "\n", set);
注意 key[]
太小了。
// char key[5] = {'A','B','C','D','E','F'}
char key[5+1] = {'A','B','C','D','E','F'}
// or
char key[] = {'A','B','C','D','E','F'}
以及为什么打印 st[0]
// printf("%c",st[0]);
printf("%c",st[i]);
即使进行了修复,OP 的最终目标也不明确也无法实现。
您的代码中存在多个问题:
const size_t SETSIZE = sizeof(uint64_t) << 3;
字节可能不是 8 位,您应该使用 const size_t SETSIZE = 64;
,因为 uint64_t
类型(如果存在)被定义为恰好 64 位宽,并具有 2 的补码表示形式。
char key[5] = { 'A', 'B', 'C', 'D', 'E', 'F' }
初始化器有 6 个字符,但显式大小设置为 5
。使用 char key[] = { 'A', 'B', 'C', 'D', 'E', 'F' };
。请注意 key
不是 C 字符串,因为初始值设定项中不存在 '[=26=]'
。另请注意,初始化程序末尾缺少 ;
。
uint64_t set_encode(char *st) {
你不修改st
指向的字符串,使用const char *st
int i, j;
i
和 j
应定义为 size_t
以与 length
.
uint64_t set = 0;
int length = strlen(st);
return类型为size_t
,因为字符串的长度可能大于int
的范围。在您的特定情况下,它不是基础函数,因为该函数仅对最多 64 个字符的字符串有用,您还应该对此进行测试。
for (i = 0; i < length; i++) {
for (j = 0; j < 5; j++) {
j
应与 sizeof(key)
.
if (st[i] == key[j]) {
printf("%c", st[0]);
您可能想要打印 st[i]
而不是 st[0]
。
set = set | 1 << (SETSIZE - 1 - i);
使用从最低值到最高值的位可能更一致,并且 1
必须转换为 (uint64_t)
以避免 int
上的算术溢出超过 31 个字符的字符串(如果 int
是 32 位宽):set = set | (uint64_t)1 << i;
。但是请注意,即使进行转换,对于大于 63 或负数的移位量,移位操作仍未定义。
}
}
}
printf("%lu\n", set);
set
不一定是 long
。您可以将其打印为至少 64 位宽的 unsigned long long
:printf("%llu\n", (unsigned long long)set);
或者您可以使用 <inttypes.h>
中的格式说明符:printf("%"PRIu64"\n", set);
return set;
}
这是更正后的版本:
const size_t SETSIZE = 64;
char key[] = { 'A', 'B', 'C', 'D', 'E', 'F' };
uint64_t set_encode(const char *st) {
uint64_t set = 0;
size_t length = strlen(st);
if (length > SETSIZE) {
printf("string too long: %zd bytes\n", length);
length = SETSIZE;
}
for (size_t i = 0; i < length; i++) {
for (size_t j = 0; j < sizeof(key); j++) {
if (st[i] == key[j]) {
printf("%c", st[i]);
set |= (uint64_t)1 << i;
}
}
}
printf("%llu\n", (unsigned long long)set);
return set;
}