我正在进行"伙伴分配"用于C中的内存管理项目(参见page 14 of this .pdf)。
我想找到"好友"对于给定地址,知道两个伙伴只有一位不同(块的大小告诉我们哪个位发生了变化)。例如,如果两个32位伙伴块中的一个具有二进制地址0b110 0 10100,则第二个将位于0b110 1 10100(来自第6位)正确的变化,如32 = 2 ^(6-1))。
我想在没有取幂算法的情况下在C中实现它,因为我试图让我的程序尽可能快地执行。充其量我会使用工具来操作位,如果存在的话。任何提示?
编辑:地址类型为 void * 。通过下面发布的解决方案, gcc 不会让我编译。
EDIT2:我已经尝试过使用XOR运算符发布的下面的答案,但由于地址的类型,我无法编译。以下是我尝试过的内容:
INSERT INTO tablename (id, ip, total) VALUES (1, xxx.xxx.x.x, 1)
ON DUPLICATE KEY UPDATE total = total+1;
和 gcc 错误:
void* ptr1 = mmap(NULL, 640000, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_FILE | MAP_PRIVATE, -1, 0);
printf("%p\n", ptr1);
void* ptr2 = ptr1+0x15f6d44;
printf("%p\n", ptr2);
void* ptr3 = (void*)(ptr2-ptr1);
printf("%p\n", ptr3);
void* ptr4 = ptr3 ^ (1 << 6);
printf("%p\n", ptr4);
答案 0 :(得分:4)
看起来您只想切换给定位,这是使用XOR操作实现的:
buddy_adr = (unsigned long)adr ^ (1 << bit_location);
需要转换为unsigned long
以避免类型void*
上的未定义XOR操作错误。
根据您的编译器设置,您可能还会收到有关通过转换整数来创建指针(即地址)的警告,这在一般情况下显然很危险(您可以传递无效的地址值)。要将此警告静音,请将结果转回void*
,让编译器知道您知道自己在做什么:
buddy_adr = (void *)((unsigned long(adr ^ (1 << bit_location));
请注意,在嵌入式系统编程中(我大部分时间都使用过这种技术,因为许多外设都是内存映射的),你通常可以简化&#34;这行代码使用TOGGLE_BIT(addr, bit)
和INT_TO_ADDR(addr)
等宏。
答案 1 :(得分:3)
您可以按位|
或。
adr = adr | 0x10;
答案 2 :(得分:3)
一个工具?操纵位?你不需要一个&#34;工具&#34;,这就像你可以做的原始操作一样。
uint32_t address = 0x0194;
address |= 1 << 5; /* This sets the sixth bit. */
如果你真的想切换这个位,即设置它是否清除,但如果设置清除它,则使用按位XOR运算符:
address ^= 1 << 5;
这是不&#34;取词&#34;,它只是一个按位异或。
如果地址保存在指针寄存器中,则转换或复制到整数(uintptr_t
)并复制回来。
答案 3 :(得分:2)
这是位操作的情况,这在c编程中非常常见 如果你想改变xxbxxxxx,只需用xx1xxxxx对此进行异或。 XOR推翻给定位。如果你想使它1只使用OR(|)所有位0,除了你要打开的位1
答案 4 :(得分:1)
更简洁的方法
#define BIT_ON(x,bit) (x |= ( 1 << (bit-1)) )
#define BIT_TOGGLE(x,bit) (x ^= ( 1 << (bit-1)) )
#define BIT_OFF(x,bit) (x &= ~( 1 << (bit-1)) )