当前位置:  开发笔记 > 编程语言 > 正文

二进制文字?

如何解决《二进制文字?》经验,为你挑选了8个好方法。

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

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!!"
}

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

const int has_nukes        = 0b00000000000000000000000000000001;
const int has_bio_weapons  = 0b00000000000000000000000000000010;
const int has_chem_weapons = 0b00000000000000000000000000000100;
// ...

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



1> sasha.sochka..:

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

0b010101010 /* more zeros and ones */

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



2> Tometzky..:

我使用位移操作符:

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;

它甚至比0的泛滥更好.


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

3> Johannes Sch..:

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

template
constexpr int operator "" _b() {
    return conv2bin::value;
}

int main() {
    int const v = 110110110_b;
}

conv2bin 将是这样的模板:

template
struct conv2bin;

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

template
struct conv2bin {
    static_assert(high == '0' || high == '1', "no bin num!");
    static int const value = (high - '0');
};

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

广义常数表达式.

Variadic模板.可在此处找到简要介绍

静态断言(static_assert)

用户定义的文字

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


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

4> 小智..:

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

#include 

const std::bitset <32> has_nukes( "00000000000000000000000000000001" );


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

5> Jon B..:

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

int hasNukes = 1;
int hasBioWeapons = 1 << 1;
int hasChemWeapons = 1 << 2;


谢谢,这甚至比0b0000 ...更好.

6> bluebrother..:

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



7> Anonymous..:

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

还有一个名为BOOST_BINARY的东西.



8> Mark Pim..:

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

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
 */

推荐阅读
虎仔球妈_459
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有