二进制文字?

Fra*_*ank 49 c++

在代码中,我有时会看到人们以十六进制格式指定常量,如下所示:

const int has_nukes        = 0x0001;
const int has_bio_weapons  = 0x0002;
const int has_chem_weapons = 0x0004;
// ...
int arsenal = has_nukes | has_bio_weapons | has_chem_weapons; // all of them
if(arsenal &= has_bio_weapons){
  std::cout << "BIO!!"
}
Run Code Online (Sandbox Code Playgroud)

但是我在这里使用十六进制格式没有意义.有没有办法直接用二进制文件做?像这样的东西:

const int has_nukes        = 0b00000000000000000000000000000001;
const int has_bio_weapons  = 0b00000000000000000000000000000010;
const int has_chem_weapons = 0b00000000000000000000000000000100;
// ...
Run Code Online (Sandbox Code Playgroud)

我知道C/C++编译器不会编译它,但必须有一个解决方法吗?是否有可能在其他语言如Java?

sas*_*hka 70

在C++ 14中,您将能够使用以下语法的二进制文字:

0b010101010 /* more zeros and ones */
Run Code Online (Sandbox Code Playgroud)

此功能在最新的已经实施clanggcc.如果您使用-std=c++1y选项运行这些编译器,则可以尝试使用它.


Tom*_*zky 62

我使用位移操作符:

const int has_nukes        = 1<<0;
const int has_bio_weapons  = 1<<1;
const int has_chem_weapons = 1<<2;
// ...
int dangerous_mask = has_nukes | has_bio_weapons | has_chem_weapons;
bool is_dangerous = (country->flags & dangerous_mask) == dangerous_mask;
Run Code Online (Sandbox Code Playgroud)

它甚至比0的泛滥更好.

  • 我的猜测是,旧的编译器非常愚蠢到实际上将1移位,而不是将该表达式转换为整数字面值. (4认同)
  • 使用这种语法时要注意的一点是,如果你将类型改为更宽的整数类型(例如``unsigned long long`),你必须将所有的`1 << N`改为`1ULL << N`,至少对于大的'N`,否则可能会发生无声的不可预测的行为(如果你很幸运,你会收到编译器警告)!(这与十六进制语法相比,您不需要添加特殊后缀,因为编译器将选择足够大的整数类型.) (3认同)

Joh*_*itb 35

顺便说一句,下一个C++版本将支持用户定义的文字.它们已经包含在工作草案中.这允许那种东西(让我希望我没有太多的错误):

template<char... digits>
constexpr int operator "" _b() {
    return conv2bin<digits...>::value;
}

int main() {
    int const v = 110110110_b;
}
Run Code Online (Sandbox Code Playgroud)

conv2bin 将是这样的模板:

template<char... digits>
struct conv2bin;

template<char high, char... digits>
struct conv2bin<high, digits...> {
    static_assert(high == '0' || high == '1', "no bin num!");
    static int const value = (high - '0') * (1 << sizeof...(digits)) + 
                             conv2bin<digits...>::value;
};

template<char high>
struct conv2bin<high> {
    static_assert(high == '0' || high == '1', "no bin num!");
    static int const value = (high - '0');
};
Run Code Online (Sandbox Code Playgroud)

好吧,我们得到的是二进制文字,在编译时已经完全评估,因为上面的"constexpr".以上使用硬编码的int返回类型.我想甚至可以使它依赖于二进制字符串的长度.对于任何感兴趣的人,它都使用以下功能:

实际上,当前的GCC trunk 已经实现了可变参数模板和静态断言.我们希望它能尽快支持其他两个.我认为C++ 1x将会震撼整个房子.

  • 什么是"下一个C++版本"是什么意思?你的回答是2009年的C++ 11吗? (3认同)
  • 我发现用户文字已集成到C ++ 11中:[用户定义的文字(自C ++ 11起-cppreference.com)(http://en.cppreference.com/w/cpp/language/user_literal) (2认同)

小智 16

C++标准库是你的朋友:

#include <bitset>

const std::bitset <32> has_nukes( "00000000000000000000000000000001" );
Run Code Online (Sandbox Code Playgroud)

  • 或者用const int has_nukes = bitset <32>("10101101").to_ulong(); (5认同)
  • 哈,那太好了.对于我们中的纯粹主义者来说,唯一的缺点似乎是它必须在运行时解析字符串以分配值.有了BOOST_BINARY,这里有人指出,这是没有必要的. (3认同)

Jon*_*n B 13

如果你愿意,可以使用<<.

int hasNukes = 1;
int hasBioWeapons = 1 << 1;
int hasChemWeapons = 1 << 2;
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这甚至比0b0000 ...更好. (2认同)

blu*_*her 13

自4.3以来,GCC支持二进制常量作为扩展.请参阅公告(请参阅"新语言和语言特定改进"部分).


Ano*_*ous 9

这个讨论可能很有意思 ......可能一直存在,因为链接已经不幸了.它描述了一种类似于其他答案的基于模板的方法.

还有一个名为BOOST_BINARY的东西.


Mar*_*Pim 9

你想要的术语是二进制文字

Ruby使用您提供的语法.

另一种方法是定义辅助宏以便为您进行转换.我在http://bytes.com/groups/c/219656-literal-binary找到了以下代码

/* Binary constant generator macro
 * By Tom Torfs - donated to the public domain
 */

/* All macro's evaluate to compile-time constants */

/* *** helper macros *** */

/* turn a numeric literal into a hex constant
 * (avoids problems with leading zeroes)
 * 8-bit constants max value 0x11111111, always fits in unsigned long
 */
#define HEX_(n) 0x##n##LU

/* 8-bit conversion function */
#define B8_(x) ((x & 0x0000000FLU) ?   1:0) \
             | ((x & 0x000000F0LU) ?   2:0) \
             | ((x & 0x00000F00LU) ?   4:0) \
             | ((x & 0x0000F000LU) ?   8:0) \
             | ((x & 0x000F0000LU) ?  16:0) \
             | ((x & 0x00F00000LU) ?  32:0) \
             | ((x & 0x0F000000LU) ?  64:0) \
             | ((x & 0xF0000000LU) ? 128:0)

/* *** user macros *** /

/* for upto 8-bit binary constants */
#define B8(d) ((unsigned char) B8_(HEX_(d)))

/* for upto 16-bit binary constants, MSB first */
#define B16(dmsb, dlsb) (((unsigned short) B8(dmsb) << 8) \
                                         | B8(dlsb))

/* for upto 32-bit binary constants, MSB first */
#define B32(dmsb, db2, db3, dlsb) (((unsigned long) B8(dmsb) << 24) \
                                 | ((unsigned long) B8( db2) << 16) \
                                 | ((unsigned long) B8( db3) <<  8) \
                                 |                  B8(dlsb))

/* Sample usage:
 * B8(01010101) = 85
 * B16(10101010,01010101) = 43605
 * B32(10000000,11111111,10101010,01010101) = 2164238933
 */
Run Code Online (Sandbox Code Playgroud)