C 如何设置4字节长度的底部3个字节,同时保持顶部字节不变?
相关代码如下:C 如何设置4字节长度的底部3个字节,同时保持顶部字节不变?,c,bit-manipulation,bitwise-and,C,Bit Manipulation,Bitwise And,相关代码如下: typedef unsigned long int chunk_head; typedef struct malloc_chunk { // Contains the size of the data in the chunk and the flag byte. chunk_head head; // Deliberately left unsized to allow overflow. // Contains the payl
typedef unsigned long int chunk_head;
typedef struct malloc_chunk
{
// Contains the size of the data in the chunk and the flag byte.
chunk_head head;
// Deliberately left unsized to allow overflow.
// Contains the payload of the chunk.
unsigned int data[];
};
举个例子,“get”宏是这样的:
//Get the size of the data contained within the chunk.
#define GET_CHUNK_SIZE(chunk) ((chunk.head) & 0xFFFFFF)
我正在使用高位字节作为标志--“inuse”和“can coalized”,我发现的任何其他字节都是有用的
现在我已经提供了背景信息,正如我在标题中所说的,我需要能够将较低的3个字节更改为块的大小。我最初的直觉是按位和标题大小对齐,因为它会正确对齐,但后来我意识到它可能也会覆盖标志字节,因为它会自动在零之前加上前缀,直到它的大小与长字符匹配为止。我甚至不确定你能不能按位,一个int和一个long。无论如何,非常感谢您的帮助。chunk.head=(chunk.head&~0xffffffL)|(新的低位)
chunk.head=(chunk.head&~0xffffffL)|(新的低位)
head = (head & 0xff000000) | (new_size & 0x00ffffff)
那么:
head = (head & 0xff000000) | (new_size & 0x00ffffff)
这就是你的意思还是我错过了什么
// retain the old top 8 bits
chunk.head &= 0xFF00000000
// set the lower 24 bits
chunk.head |= (0x00FFFFFF & new_bits)
这就是你的意思还是我遗漏了什么?由于某种原因,到目前为止,你收到的大多数回复都坚持要彻底解决潜在的大小溢出问题,即,他们使用
0x00FFFFFF
来“和”块大小,从而悄悄地丢弃过多的大小位(如果有的话)然后继续将完全没有意义的大小尾部写入字段。我不知道为什么会有人做那样的事
// retain the old top 8 bits
chunk.head &= 0xFF00000000
// set the lower 24 bits
chunk.head |= (0x00FFFFFF & new_bits)
更合理的代码可能如下所示
assert((size & 0xFF000000) == 0);
chunk.head = (chunk.head & 0xFF000000) | size;
没有有效的理由使用
0x00FFFFFF
来“和”大小。您应该中止或至少断言过多的大小,而不是悄悄地丢弃过多的大小。由于某种原因,您迄今收到的大多数回复都坚持要彻底解决潜在的大小溢出问题,即,它们使用0x00FFFFFF
来“和”块大小,从而悄悄地丢弃过多的大小位(如果有)然后继续将完全没有意义的大小尾部写入字段。我不知道为什么会有人做那样的事
更合理的代码可能如下所示
assert((size & 0xFF000000) == 0);
chunk.head = (chunk.head & 0xFF000000) | size;
没有有效的理由使用
0x00FFFFFF
来“和”大小。您应该中止或至少断言过多的大小,而不是悄悄地丢弃过多的大小。使用位字段来执行此操作。它避免了使用宏,在调试器中也很好:
typedef struct chunk_head {
unsigned size:24;
unsigned inuse:1;
unsigned cancoalesce:1;
// Room for 6 more...
};
typedef struct malloc_chunk {
struct chunk_head head;
int data[];
};
使用位字段执行此操作。它避免了使用宏,在调试器中也很好:
typedef struct chunk_head {
unsigned size:24;
unsigned inuse:1;
unsigned cancoalesce:1;
// Room for 6 more...
};
typedef struct malloc_chunk {
struct chunk_head head;
int data[];
};
几乎正确,但
|=
意味着您永远无法清除大小部分中的位。我怀疑=
更合适。几乎正确,但|=
意味着您永远无法清除大小部分中的位。我怀疑=
更合适。我知道大小永远不会超过3字节(准确地说是15位),因此我可以安全地丢弃“&0x00ffffff”部分,对吗?是;如果大小不可能超过三个字节,或者您在代码中进行了检查以保证不会超过三个字节,那么您可以放弃该&
。如果新的大小可能超过三字节,你可以考虑使用断言来帮助在调试期间发现错误,根据AndreyT的建议。我知道大小永远不会超过3字节(确切地说是15位),所以我可以安全地丢弃“& 0x00 FFFFFF”部分,对吗?如果大小不可能超过三个字节,或者您在代码中进行了检查以保证不会超过三个字节,那么您可以放弃该&
。如果新的大小可能超过三字节,你可以考虑使用断言来帮助在调试期间发现错误,根据AndreyT的建议。只有我没有这样做的理由(相信我,我考虑使用它们很长时间)是,所有的报告,编译器产生比掩码更优化的掩码代码。而且,因为我需要尽我所能提高每一点性能,所以我选择了速度更快的代码。我没有这么做的唯一原因(相信我,我考虑了很长一段时间)是,根据所有报告,编译器为掩码生成的优化代码比为位字段生成的优化代码要多。因为我需要尽我所能弥补每一点性能,我选择了更快的代码。