hyp*_*gic 130 c c++ binary bit-fields
我已经看到这种模式在C&C++中使用了很多.
unsigned int flags = -1; // all bits are true
Run Code Online (Sandbox Code Playgroud)
这是一个很好的便携式方法吗?或正在使用0xffffffff或~0更好?
Joh*_*itb 152
我建议你完全按照你所展示的那样去做,因为它是最直接的.初始化-1将始终有效,独立于实际符号表示,~有时会出现令人惊讶的行为,因为您必须具有正确的操作数类型.只有这样,您才能获得最高价值的unsigned类型.
有关可能出现意外的示例,请考虑以下问题:
unsigned long a = ~0u;
Run Code Online (Sandbox Code Playgroud)
它不一定存储所有位1的模式a.但它首先会创建一个包含所有位1的模式unsigned int,然后将其分配给a.当unsigned long有更多位时会发生什么,并非所有这些都是1.
并考虑这一个,它将失败的非二进制补码表示:
unsigned int a = ~0; // Should have done ~0u !
Run Code Online (Sandbox Code Playgroud)
原因是~0必须反转所有位.反转将产生-1两个补码机器(这是我们需要的值!),但不会屈服于-1另一个表示.在一个补码机器上,它产生零.因此,在一个补码机器上,上面将初始化a为零.
你应该理解的是,所有这些都与价值观有关 - 而不是比特.变量用值初始化.如果在初始值设定项中修改了用于初始化的变量的位,则将根据这些位生成该值.初始化a为最高可能值所需的值是-1或UINT_MAX.第二个将取决于a你需要使用ULONG_MAX的类型unsigned long.但是,第一个不依赖于它的类型,这是获得最高价值的好方法.
我们不是在谈论是否-1所有位都是(它并不总是).而且我们不是在谈论是否~0所有位都是(当然它有).
但我们所说的是初始化flags变量的结果是什么.对于它,只-1适用于所有类型和机器.
Din*_*ngo 48
unsigned int flags = -1; 是便携式的.unsigned int flags = ~0; 不可移植,因为它依赖于二进制补码表示.unsigned int flags = 0xffffffff; 不可移植,因为它采用32位整数.如果要以C标准保证的方式设置所有位,请使用第一个.
Dou*_* T. 25
坦率地说,我认为所有的fff都更具可读性.至于它是反模式的评论,如果你真的关心所有的位都被设置/清除,我会争辩说你可能处于这样一种情况,你无论如何都要关心变量的大小,这会要求像boost这样的东西:: uint16_t等
ham*_*mar 17
避免上述问题的一种方法是简单地做:
unsigned int flags = 0;
flags = ~flags;
Run Code Online (Sandbox Code Playgroud)
便携式和重点.
Edo*_* A. 13
我不确定在C++中首先使用unsigned int for flags是一个好主意.比特怎么样?
std::numeric_limit<unsigned int>::max()更好,因为0xffffffff假设unsigned int是一个32位整数.
Adr*_*thy 11
Run Code Online (Sandbox Code Playgroud)unsigned int flags = -1; // all bits are true"这是一个很好的[,]便携式方法吗?"
便携式? 是的.
好? 辩论,这个线程上显示的所有混乱都证明了这一点.足够清楚,你的程序员可以毫不混淆地理解代码,这应该是我们衡量好代码的维度之一.
此外,此方法易于出现编译器警告.要在不破坏编译器的情况下忽略警告,您需要显式强制转换.例如,
unsigned int flags = static_cast<unsigned int>(-1);
Run Code Online (Sandbox Code Playgroud)
显式强制转换要求您注意目标类型.如果你关注目标类型,那么你自然会避免其他方法的陷阱.
我的建议是关注目标类型并确保没有隐式转换.例如:
unsigned int flags1 = UINT_MAX;
unsigned int flags2 = ~static_cast<unsigned int>(0);
unsigned long flags3 = ULONG_MAX;
unsigned long flags4 = ~static_cast<unsigned long>(0);
Run Code Online (Sandbox Code Playgroud)
所有这些都是正确的,对你的程序员来说更明显.
使用C++ 11:我们可以使用auto以下任何一个更简单:
auto flags1 = UINT_MAX;
auto flags2 = ~static_cast<unsigned int>(0);
auto flags3 = ULONG_MAX;
auto flags4 = ~static_cast<unsigned long>(0);
Run Code Online (Sandbox Code Playgroud)
我认为正确和明显优于简单正确.
R..*_*R.. 10
标准保证将-1转换为任何无符号类型以产生全1.使用~0U通常是坏的,因为0有类型unsigned int并且不会填充更大的无符号类型的所有位,除非你明确地写了类似的东西~0ULL.在理智的系统上,~0应该是相同的-1,但由于标准允许补码和符号/幅度表示,严格来说它不是便携式的.
当然,0xffffffff如果你知道你需要正好32位,那么写出来总是可以的,但是-1的优势在于它可以在任何环境中工作,即使你不知道类型的大小,例如可以在多种类型上工作的宏,或者如果类型的大小因实施而异.如果你知道的类型,另一种安全的方式来获得所有的人已是极限宏UINT_MAX,ULONG_MAX,ULLONG_MAX,等.
我个人总是使用-1.它总是有效,你不必考虑它.
只要你有#include <limits.h>一个包含,你就应该使用
unsigned int flags = UINT_MAX;
Run Code Online (Sandbox Code Playgroud)
如果你想要一个很长的比特,你可以使用
unsigned long flags = ULONG_MAX;
Run Code Online (Sandbox Code Playgroud)
无论如何实现有符号整数,这些值都保证将结果集的所有值位都设置为1.
是.如其他答案所述,-1是最便携的; 但是,它不是非常语义并且会触发编译器警告.
要解决这些问题,请尝试以下简单的帮助:
static const struct All1s
{
template<typename UnsignedType>
inline operator UnsignedType(void) const
{
static_assert(std::is_unsigned<UnsignedType>::value, "This is designed only for unsigned types");
return static_cast<UnsignedType>(-1);
}
} ALL_BITS_TRUE;
Run Code Online (Sandbox Code Playgroud)
用法:
unsigned a = ALL_BITS_TRUE;
uint8_t b = ALL_BITS_TRUE;
uint16_t c = ALL_BITS_TRUE;
uint32_t d = ALL_BITS_TRUE;
uint64_t e = ALL_BITS_TRUE;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
33604 次 |
| 最近记录: |