使用-1将所有位设置为true是否安全?
我已经看到这种模式在C&C ++中使用了很多。
unsigned int flags = -1; // all bits are true  这是一个很好的便携式的方式来完成这个? 或者是使用0xffffffff或0xffffffff更好? 
 我build议你完全按照你所说的去做,因为这是最直接的。 初始化为-1将始终工作,独立于实际的符号表示,而~有时会有令人惊讶的行为,因为你将不得不有正确的操作数types。 只有这样你才能得到unsignedtypes的最高值。 
举一个可能的惊喜的例子,考虑一下:
 unsigned long a = ~0u; 
 它不一定将所有比特1的模式存储到a 。 但它将首先创build一个unsigned int所有位为1的模式,然后将其分配给a 。 当unsigned long有更多位时会发生什么,并不是所有的都是1。 
并考虑这个,这将在一个非二的补码表示失败:
 unsigned int a = ~0; // Should have done ~0u ! 
 原因是〜0必须反转所有位。 反过来,在二进制补码机器(这是我们需要的值!)上将产生-1 ,但在另一个表示上不会产生-1 。 在补码机上,它会产生零。 因此,在一台补码机上,上面将初始化为零。 
 你应该明白的是,这一切都是关于价值 – 而不是一点点。 variables用一个值初始化。 如果在初始化器中修改用于初始化的variables的位,则会根据这些位生成值。 您需要将初始化为最高可能值的值为-1或UINT_MAX 。 第二个将取决于types – 您将需要使用ULONG_MAX作为unsigned long 。 然而,第一个不会取决于它的types,这是获得最高价值的好方法。 
  我们不是在讨论-1是否全部是第一位(它并不总是)。  而且我们不是在讨论〜0是否全部是第一(当然是)。 
 但是我们所说的是初始化flagsvariables的结果。 而对于它, 只有-1会适用于所有types和机器。 
-  unsigned int flags = -1;是便携式的。
-  unsigned int flags = ~0;是不可移植的,因为它依赖于二进制补码表示。
-  unsigned int flags = 0xffffffff;不可移植,因为它假定32位整数。
如果你想以C标准保证的方式设置所有的位,使用第一个。
坦率地说,我认为所有的fff更具可读性。 至于它是一个反模式的评论,如果你真的关心所有的位被设置/清除,我会争辩说,你可能在你关心variables的大小的情况下,这将需要像boost :: uint16_t等
避免提到的问题的一个方法是简单地做:
 unsigned int flags = 0; flags = ~flags; 
便携式和重点。
我不确定在C ++中使用unsigned int标志是一个好主意。 那么bitset之类的呢?
  std::numeric_limit<unsigned int>::max()更好,因为0xffffffff假定unsigned int是一个32位整数。 
unsigned int flags = -1; // all bits are true“这是一个很好的,便携的方式来完成这个吗?”
便携式? 是的 。
好? 可疑的 ,这个线程显示的所有困惑都certificate了这一点。 要清楚你的程序员能够理解代码而不会混淆,这应该是我们衡量好代码的一个维度。
另外,这种方法很容易出现编译器警告 。 为了避免危害编译器,你需要明确的强制转换。 例如,
 unsigned int flags = static_cast<unsigned int>(-1); 
明确的转换要求您注意目标types。 如果你注意目标types,那么你自然会避免其他方法的陷阱。
我的build议是注意目标types,并确保没有隐式转换。 例如:
 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); 
所有这些对你的程序员来说都是正确和明显的 。
  而在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); 
我认为正确和明显比简单正确。
 将-1转换为任何无符号types由标准保证为全1。 使用~0U通常是不好的,因为0types是unsigned int并且不会填充更大的无符号types的所有位,除非明确地写入类似~0ULL东西。 在理智的系统中,〜0应该与-1相同,但是由于标准允许补码和符号/幅度表示,所以严格来说这不是可移植的。 
 当然,如果你知道你只需要32位就可以写出0xffffffff ,但是-1的好处是它可以在任何情况下工作,即使你不知道这个types的大小,例如在多个types,或者如果types的大小因实现而不同。 如果确实知道types,则另一种获得全部内容的安全方法是限制macrosUINT_MAX , ULONG_MAX , ULLONG_MAX等。 
我个人总是用-1。 它总是有效的,你不必考虑它。
 是。 正如其他答案中提到的, -1是最便携的; 但是,它不是很有意义,并触发编译器警告。 
要解决这些问题,试试这个简单的帮手:
 static const struct All1s { template<typename UnsignedType> inline operator UnsignedType(void) const { return static_cast<UnsignedType>(-1); } } ALL_BITS_TRUE; 
用法:
 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; 
 只要你包含#include <limits.h> ,你就可以使用 
 unsigned int flags = UINT_MAX; 
如果你想要一个很长的价值,你可以使用
 unsigned long flags = ULONG_MAX; 
这些值保证将结果集的所有值都设置为1,而不pipe签名整数如何实现。
我不会做-1的事情。 这是相当不直观的(至less对我来说)。 将签名数据分配给一个无符号variables似乎是违反了事物的自然顺序。
 在你的情况下,我总是使用0xFFFF 。  (使用正确数量的Fs作为当然的可变尺寸。) 
[顺便说一下,我很less看到在现实世界代码中完成的-1技巧。]
 另外,如果你真的关心可放大的单个位,开始使用固定宽度的uint8_t , uint16_t , uint32_ttypes是个好主意。 
在英特尔的IA-32处理器上写入0xFFFFFFFF到64位寄存器并得到预期的结果是可以的。 这是因为IA32e(IA32的64位扩展)仅支持32位立即数。 在64位指令中,32位立即数被符号扩展为64位。
以下是非法的:
 mov rax, 0ffffffffffffffffh 
以下是在RAX中放置64个1:
 mov rax, 0ffffffffh 
为了完整起见,下面在RAX(又名EAX)的下半部分放置32个1:
 mov eax, 0ffffffffh 
事实上,当我想将0xffffffff写入64位variables时,程序就会失败,取而代之的是0xffffffffffffffff。 在C这将是:
 uint64_t x; x = UINT64_C(0xffffffff) printf("x is %"PRIx64"\n", x); 
结果是:
 x is 0xffffffffffffffff 
我想这张贴作为评论,所有的答案,说0xFFFFFFFF假设32位,但有这么多人回答,我想我会添加它作为一个单独的答案。
请参阅litb的答案,对问题做出非常清晰的解释。
我的不同意是,严格来说,这两种情况都不能保证。 我并不知道任何体系结构并不代表所有位设置的'1位小于2的无符号值'的无符号值,但这是标准实际所说的(3.9.1 / 7加附注44):
整体types的表示应使用纯二进制数字系统来定义值。 [注释44:]使用二进制数字0和1的整数的位置表示,其中由连续位表示的值是加法的,以1开始,并且乘以2的连续整数幂,除了最高的位置。
这使得其中一个位的可能性是任何东西。
实际上:是的
理论上:不。
-1 = 0xFFFFFFFF(或者你的平台上int的大小)只有在二进制补码运算中才是正确的。 在实践中,它会起作用,但是那里有一些遗留的机器(IBM大型机等),在那里你有一个实际的符号位,而不是二进制补码表示。 你提出的〜0解决scheme应该到处工作。
 尽pipe0xFFFF (或0xFFFFFFFF等)可能更容易阅读,但它可能破坏本来便携的代码的可移植性。 例如,考虑一个库例程来计算数据结构中有多less项具有特定的位(被调用者指定的确切位)。 程序可能完全不知道这些位代表什么,但是仍然需要“所有位设置”恒定。 在这种情况下,-1会比一个hex常数好得多,因为它可以处理任何位的大小。 
 另一种可能性是,如果typedef值用于位掩码,则将使用〜(bitMaskType)0; 如果掩码碰巧只是一个16位的types,那么这个expression式只会设置16位(即使“int”会是32位),但是由于16位将是所有需要的,实际上在types转换中使用了适当的types。 
 顺便说一下,如果hex常量太大而不能适应int ,但是会适合一个unsigned int , longvar &= ~[hex_constant]forms的expression式会有一个令人讨厌的问题。 如果int是16位,那么longvar &= ~0x4000; 或longvar &= ~0x10000 ; 将清除longvar ,但longvar &= ~0x8000; 将清除位15以及所有位。 符合int值会将补码运算符应用于inttypes,但结果将被标记为long ,并设置高位。 对于unsigned int来说太大的值会将complement运算符应用于inputlong 。 然而,在这些大小之间的值将应用补码运算符来键入unsigned int ,然后将其转换为无符号扩展的long unsigned int 。 
正如其他人所提到的,-1是创build一个整数的正确方法,它将转换为所有位设置为1的无符号types。但是,C ++中最重要的是使用正确的types。 因此,你的问题的正确答案(包括你问的问题的答案)是这样的:
 std::bitset<32> const flags(-1); 
 这将始终包含您需要的确切数量的位。 它构造了一个std::bitset ,其所有位都设置为1,这与其他答案中提到的相同。 
 这当然是安全的,因为-1总是有所有可用的位,但是我更喜欢〜0。  -1对于一个unsigned int没有多大意义。  0xFF …不好,因为它取决于types的宽度。 
我说:
 int x; memset(&x, 0xFF, sizeof(int)); 
这总是会给你想要的结果。
 利用将所有位分配给无符号types的事实相当于为给定types取最大可能值, 
 并将问题的范围扩展到所有无符号整数types: 
指定-1对于 C和C ++都适用于任何无符号整数types (unsigned int,uint8_t,uint16_t等)。
作为替代scheme,对于C ++,您可以:
-  包括<limits>并使用std::numeric_limits< your_type >::max()
- 编写一个自定义模板函数 (这也将允许一些理智检查,即如果目标types是一个真正的无符号types)
 目的可以增加更多的清晰度,因为分配-1总是需要一些解释性的评论。 
是的,所显示的表示是非常正确的,就好像我们这样做了,反过来,你将需要一个操作符来反转所有的位,但是在这种情况下,如果我们考虑机器中整数的大小,这个逻辑非常简单
例如在大多数机器中,一个整数是2个字节= 16位最大值它可以容纳的是2 ^ 16-1 = 65535 2 ^ 16 = 65536
0%65536 = 0 -1%65536 = 65535其中1111 …………. 1,并且所有的位都被设置为1(如果我们考虑残留类mod 65536)直截了当。
我猜
没有,如果你考虑这个概念,它完全用于未签名的整数,它实际上是工作
只需检查下面的程序片段
int main(){
 unsigned int a=2; cout<<(unsigned int)pow(double(a),double(sizeof(a)*8)); unsigned int b=-1; cout<<"\n"<<b; getchar(); return 0; 
}
答案为b = 4294967295,其中4个字节的整数为-1%2 ^ 32
因此它对于无符号整数是完全有效的
如有任何不一致的情况报告