/* 转载请注明出处:http://www.cnblogs.com/Martinium/p/binary_literal.html */


二进制的语法

  C/C++ 默认数字使用十进制,八进制使用前缀 0, 十六进制使用前缀 0x 或 0X,二进制常数的提议被否决(引用 C 语言程序原理国际标准 的 6.4.4.1 章节字段 "A proposal to add binary constants was rejected due to lack of precedent and insufficient utility."),一直没有二进制的表示方法, GCC 使用 0b/0B 前缀作为扩展,其实很多编译器都有这个扩展的,只是标准委员会一直没采纳。直到 C++14 才引进,可谓姗姗来迟啊。这种二进制语义 Java 7 也早些时候引入,Python 2.6 以及后来的 3 也引入,Python 为了避免十进制与八进制的混淆,一律用字母前缀,不分大小写,0b 为二进制,0o 为八进制,ox 为十六进制。Python2 升到 Python3 时果断丢弃了原来的八进制语义(也就是在 C/C++/Java 里面有 0 前缀的八进制的语义)。
 
表示方法
1. 下面每行语句表达语义相同,只是选用不同的进制数表示。
  1. int i = 0b101010; // binary
  2. int i = ; // octal
  3. int i = ; // decimal
  4. int i = 0x2a; // hexadecimal
2. 使用 strtol/strtoll/strtoq 函数,可以将一个字符串转换成整数,base 取 2 表示转换成二进制数。
#include <stdlib.h>
long int strtol(const char *nptr, char **endptr, int base);
long long intstrtoll(const char *nptr, char **endptr, int base);

我在解密一些二进制数据的时候,用到过这个函数。先用正则表达式每八个数字一拆分 echo A_LONG_BINARY_STRING | sed -r 's/([01]{8})/\1 /g',然后利用空格作间隔符提取数字所代表的 ASCII 码,当然,你也可以用移位运算自己实现每八个数字一读的功能。

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <stdlib.h>
  4.  
  5. int main()
  6. {
  7. const char* raw = "01110101 01110011 01100101 00100000 01110111 01100101 01100100 01101110 01100101 01110011 01100100 01100001 01111001 00100000 01100110 01101111 01110010 00100000 01110100 01101000 01100101 00100000 01100001 01101110 01110011 01110111 01100101 01110010";
  8. const char* begin;
  9. char* end = const_cast<char*>(raw);
  10. do
  11. {
  12. begin = end;
  13. long int byte = strtol(begin, &end, /*base*/);
  14. putchar(static_cast<int>(byte));
  15. }while(begin != end);
  16.  
  17. return ;
  18. }
3.  也可以使用 STL 里的 bitset 完成,不仅可以用数字,也可以用其他字符表示 0/1,这个比方法 2 更强大。这种方法我在做培根密码解密题用到过,将 A/B 字符映射成 0/1 数字。

  1. // unsigned long long constructor
  2. std::bitset<> ();
  3. // string constructor
  4. std::string bits = "";
  5. std::bitset<> binary(bits); // [0,0,1,1,0,0,1,0]
  6. // string constructor using custom zero/one digits
  7. std::string bacon = "ABABB";
  8. std::bitset<> m(bacon, , std::string::npos, 'A', 'B'); // [0,1,0,1,1]
 
4. 可以使用 boost 库的 BOOST_BINARY, 可以每隔开几个数字一写,在表示很大的数时很方便阅读。
  1. int value1 = BOOST_BINARY( );
  2. unsigned long value2 = BOOST_BINARY_UL( ); // unsigned long
  3. long long value3 = BOOST_BINARY_LL( ); // long long if supported

提到方便阅读,C++14 加入了数字分隔符这个想法, 于是可以写成 double e = 2.718'281'828'459'045'; 方便阅读。

5. 如果不是一项工程,而是简短的程序,可以利用 C++ 的模板模拟二进制语义。
  1. template<unsigned long long N>
  2. struct binary
  3. {
  4. enum { value = (N%) + binary<N/>::value* };
  5. };
  6.  
  7. template<>
  8. struct binary
  9. {
  10. enum { value = };
  11. }
 
int value = static_cast<int>(binary<101010>::value);
上面的代码中, enum 是为了让变量在编译期获取结果,没有用整型。还有一个问题是如果数的开头有 0,结果可不妙。整个数被当成了八进制而不是十进制数解析,很容易滋生 bug。比较好的解决方法是数字经常以 0 开头(或添加断言强制),将十进制换成八进制。
 
 
  1. // need to enable C++11 flag
  2. template<unsigned long long>
  3. struct binary
  4. {
  5.   constexpr static int value = binary<N/>::value + N%;
  6. };
  7.  
  8. template<>
  9. struct binary<>
  10. {
  11.   constexpr static int value = ;
  12. }
6.  采用用户自定字面值(User-defined literals),注意这个是 C++11 新加的功能。之前的 C++03 内置一些类似的语义(比方说在浮点数后加字符 "f" 表示声明一个 float 而不是 double),但是用户不能自己定义。
C++11 开放用户定义新的字面修饰符(literal modifier),利用自定义的修饰符完成由字面值构造对象。所有的自定字面值必须是后置,前置是不允许的。C++11 开放用户定义新的字面修饰符(literal modifier),利用自定义的修饰符完成由字面值构造对象。除了下划线,所有的后置被标准保留。所以,用户定义时需要以下划线开头。
  1. int operator "" _B(int i);
  2. static_assert( 101010_B == 42);
 
 

C++ 的二进制语法与语义的更多相关文章

  1. assertion的语法和语义

    .1) 语法表示 在语法上,为了支持assertion,Java增加了一个关键字assert.它包括两种表达式,分别如下: assert expression1; assert expression1 ...

  2. 解读HTML 5新语法 提高语义价值

    HTML 5的新标记 设计者们需要完成的任务是要给HTML 5开发一个更丰富的和更有含义的语义,当然可以想象这种新方案将会是很灵活和很高效的,同时与所有的现代互联网标准相适应.下面就是一些将要在HTM ...

  3. Eigen与Matlab语法及语义辞典

    Eigen为Matlab转换为C++提供了一个简单的语法级别的代码迁移工具. 对一些代码进行了扩充,以便程序由Matlab到Eigen的移植................... 参考链接:http: ...

  4. HTML5经典实例——1基础语法和语义

    1指定DOCTYPE 在页面的最开始处指定HTML5 DOCTYPE DOCTYPE是不区分大小写的.可以任意的使用大小写. <!DOCTYPE html> <html lang=& ...

  5. 15.3 Task 语法和语义

    15.3.1 声明异步方法和返回类型 async static void GetStringAsync() { using (var client = new HttpClient()) { Task ...

  6. net-force.nl/steganography writeup

    做CTF题好长一段时间了,真的可以学到很多东西.这次,我们开启 net-force.nl 的 Steganography之旅,所谓的隐写术. level 801: Training - Can you ...

  7. Compiler Theory(编译原理)、词法/语法/AST/中间代码优化在Webshell检测上的应用

    catalog . 引论 . 构建一个编译器的相关科学 . 程序设计语言基础 . 一个简单的语法制导翻译器 . 简单表达式的翻译器(源代码示例) . 词法分析 . 生成中间代码 . 词法分析器的实现 ...

  8. Python3语法详解

    一.下载安装 1.1Python下载 Python官网:https://www.python.org/ 1.2Python安装 1.2.1 Linux 平台安装 以下为在Unix & Linu ...

  9. HTML标记语法之表格元素

    语法与语义: <table>和</table>定义表格的开始和结束 <thead>和</thead>定义表格头部的开始和结束 <tbody> ...

随机推荐

  1. 风口之下,猪都能飞。当今中国股市牛市,真可谓“错过等七年”。 给你一个回顾历史的机会,已知一支股票连续n天的价格走势,以长度为n的整数数组表示,

    转自:http://www.cnblogs.com/ranranblog/p/5845010.html 风口之下,猪都能飞.当今中国股市牛市,真可谓“错过等七年”. 给你一个回顾历史的机会,已知一支股 ...

  2. Android LitePal 神一般的数据库框架 超级好用

    参考: Android数据库高手秘籍(一)--SQLite命令 Android数据库高手秘籍(二)--创建表和LitePal的基本用法 Android数据库高手秘籍(三)--使用LitePal升级表 ...

  3. 还原数据库:The backup set holds a backup of a database other than the existing database……

    还原数据库时报以上错误,解决办法是: 1.删除新建的DB 2.直接右键Databases-->Restore Database 3.在弹出窗口中的To database栏位填写需要新建的DB名称 ...

  4. CSS命名规范

    DIV+CSS规范命名大全集合 前端人员必看CSS命名规范 整理: 文件名必须由小写字母.数字.中划线组成 ).所有的命名最好都小写,一律采用小写加中划线的方式,不允许使用大写字母或 _2).属性的值 ...

  5. iOS - YYAdd对UIDevice的拓展

    YYKit中对UIDevice的拓展,accumulate knowledge !!! 首先 #include <sys/socket.h> #include <sys/sysctl ...

  6. hue install

    http://ju.outofmemory.cn/entry/105162 Hue是一个开源的Apache Hadoop UI系统,最早是由Cloudera Desktop演化而来,由Cloudera ...

  7. 外景VR的应用

    留坑,续写. 最近在做外景的项目,被相关的帧率优化和灯光布置困扰的不要不要的.下面写下我是怎么优化帧率和对帧率的一些理解. 帧率,游戏的重要影响因素,会对玩家的手感以及视觉产生重大的影响,一般的游戏帧 ...

  8. sublime text3好用的插件

    1.安装package control sublime text3 的安装方法,ctrl+`,调出控制台输入 import urllib.request,os; pf = 'Package Contr ...

  9. [NHibernate]事务

    目录 写在前面 文档与系列文章 事务 增删改查 总结 写在前面 上篇文章介绍了nhibernate的增删改查方法及增加修改操作,这篇文章将介绍nhibernate的事务操作. SQL Server中的 ...

  10. itrator控制迭代次数

    <s:iterator value="diys" status="d" begin="0" end="10" st ...