C 清除常量低位字节的按位表达式

C 清除常量低位字节的按位表达式,c,bit-manipulation,C,Bit Manipulation,我正在编写可能在不同字长(32位、64位等)的体系结构上运行的代码,我希望清除值的低位字节。有一个宏(MAX)被设置为单词的最大值。例如,在32位系统上,对于无符号值,MAX=0xFFFFFFFF,在64位系统上MAX=0xffffffffffff。如果我有一个字大小的变量,可能是有符号的,也可能是无符号的,那么如何用一个表达式清除变量的低位字节(无分支) 我的第一个想法是: value & ~( MAX - 0xFF ) 但这似乎不适用于有符号值。我的另一个想法是: value =

我正在编写可能在不同字长(32位、64位等)的体系结构上运行的代码,我希望清除值的低位字节。有一个宏(MAX)被设置为单词的最大值。例如,在32位系统上,对于无符号值,MAX=0xFFFFFFFF,在64位系统上MAX=0xffffffffffff。如果我有一个字大小的变量,可能是有符号的,也可能是无符号的,那么如何用一个表达式清除变量的低位字节(无分支)

我的第一个想法是:

value & ~( MAX - 0xFF )
但这似乎不适用于有符号值。我的另一个想法是:

value = value - (value & 0xFF)
它的缺点是需要堆栈操作。

如何

value & ~((intptr_t)0xFF)

首先,您需要一个掩码,该掩码所有位都打开,但低阶字节的位除外

MAX ^ 0xFF
这将
0xFF
转换为与
MAX
相同的类型,然后使用该值执行异或运算。因为
MAX
具有所有低阶位
1
,因此这些位随后变为
0
,而高阶位保持不变,即
1

然后你必须把面具盖在你感兴趣的价值上

value & ( MAX ^ 0xFF )

若要清除低位字节,不知道整数类型宽度可能会导致错误代码。所以代码应该小心

考虑以下情况,
value
int/unsigned
0xFF
是一个值为255的
int
常量
~0xFF
则是该值及其位反转。如果对公共2进行补充,则其上限位设置为FF…FF00时为-256-256转换为更宽的有符号类型时保留其值和模式FF…FF00-转换为更宽的无符号类型的256变为
Uxxx\u MAX+1-256
,位模式为FF…FF00。在这两种情况下,
将保留高位并清除低位8

value_low_8bits_cleared = value & ~0xFF;

另一种方法是使用无符号数学执行所有屏蔽操作,以避免
int
math和
int
编码的意外属性

下面的代码不涉及符号扩展,
int
overflow。一个优化的编译器肯定会发出一个简单而有效的代码掩码。此外,不需要对与
相对应的正确匹配最大值进行编码

value_low_8bits_cleared = (value | 0xFFu) ^ 0xFFu;

以下是清除低位8位的简单方法:

value &= ~0xFF;
我正在编写可以在不同字数的体系结构上运行的代码 (32位、64位等)我想清除值的低位字节

有一个宏(MAX)被设置为单词的最大值。所以 例如,在32位系统上,MAX=0xFFFFFFFF,在64位系统上 对于无符号值,系统最大值=0xFFFFFFFFFFFFFF

尽管C语言的设计使得实现可以考虑机器词的大小,但该语言本身并没有机器词的固有含义。C关心的是类型,这就不同了

无论如何,我完全按照您的话来理解,您将macro
MAX
的替换文本作为您给出的两个备选文本之一,具体取决于机器的体系结构。请注意,当替换文本被解释为整数常量时,其类型在C实现之间可能会有所不同,甚至可能取决于编译器选项

如果我有 字大小的变量,可以是有符号的或无符号的,如何清除 具有单个表达式的变量的低位字节(无分支)

我认为需要一个表达式而不能显式地考虑实际类型的
的唯一原因是希望在宏本身中使用该表达式。在这种情况下,您需要特别注意类型转换,尤其是当您必须考虑签名类型时。这会使您的
MAX
宏不适合用于您的目的

我倾向于建议一种不同的方法:

(value | 0xFF) ^ 0xFF

常量
0xFF
将被解释为(有符号)
int
带正值。如果
value
的类型不小于
int
,则
0xFF
的两种外观都将转换为该类型,而不改变值,无论该类型是有符号的还是无符号的。此外,每个操作和整个表达式的结果的类型与
value
相同,因此不会发生意外的转换。

在任何(8位字节)上使用
~0xFF
进行ANDing,以清除低位字节体系结构。请注意,
MAX
的扩展类型独立于表达式中的其他变量和值的类型,例如您所呈现的类型。不过,总的来说,我不太清楚你想克服什么问题。我一直在想,有些维度我还没有意识到,没有一个字大小的变量可以是有符号的,也可以是无符号的。你要么签字,要么不签字。问题到处都是。首先,你说你正在使用一个常数。然后它突然变成了一个可能是“有符号或无符号”的变量。那么,它是什么:变量还是常数?你需要下决心。首先,从图片中去掉“签名”。不允许签名。您仅使用未签名的。如果您需要签名,您将在以后转换结果。在实践中,这可能在任何地方都适用。然而,重要的是,它可能涉及将
value
转换为type
intptr\u t
,并可能根据表达式的使用方式进行其他转换。与其使用
intptr\u t
,不如使用
uintmax\u t
MAX^0xFF
的描述不正确。低阶位被反转。如果
MAX
没有以
0xFF
结尾,则它将不起作用。可以工作的是
value&(value^0xFF)
@EugeneSh.,
MAX
在问题中被描述为类型的最大值。因此它有一个