Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何设置4字节长度的底部3个字节,同时保持顶部字节不变?_C_Bit Manipulation_Bitwise And - Fatal编程技术网

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的建议。只有我没有这样做的理由(相信我,我考虑使用它们很长时间)是,所有的报告,编译器产生比掩码更优化的掩码代码。而且,因为我需要尽我所能提高每一点性能,所以我选择了速度更快的代码。我没有这么做的唯一原因(相信我,我考虑了很长一段时间)是,根据所有报告,编译器为掩码生成的优化代码比为位字段生成的优化代码要多。因为我需要尽我所能弥补每一点性能,我选择了更快的代码。