/* 转载请注明出处: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. 下面每行语句表达语义相同,只是选用不同的进制数表示。
int i = 0b101010;  // binary
int i = ; // octal
int i = ; // decimal
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 码,当然,你也可以用移位运算自己实现每八个数字一读的功能。

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h> int main()
{
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";
const char* begin;
char* end = const_cast<char*>(raw);
do
{
begin = end;
long int byte = strtol(begin, &end, /*base*/);
putchar(static_cast<int>(byte));
}while(begin != end); return ;
}
3.  也可以使用 STL 里的 bitset 完成,不仅可以用数字,也可以用其他字符表示 0/1,这个比方法 2 更强大。这种方法我在做培根密码解密题用到过,将 A/B 字符映射成 0/1 数字。

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

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

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

    using System; using System.Drawing; using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; na ...

  2. a版本冲刺第四天

    队名:Aruba   队员: 黄辉昌 李陈辉 林炳锋 鄢继仁 张秀锋 章  鼎 学号 昨天完成的任务 今天做的任务 明天要做的任务 困难点 体会 408 完成学习Java从入门到精通基础篇 通读了构建 ...

  3. Java内存模型深度解读

    Java内存模型规范了Java虚拟机与计算机内存是如何协同工作的.Java虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型——又称为Java内存模型. 如果你想设计表现良好的并发 ...

  4. ArcEngine地图窗口指定区域导出指定DPI多格式---delphi/C#实现

    delphi/C#实现,其他语言稍微改下就行了.AE的编码各个语言都差不多,这里也没用到某一语言的特性. 函数特点: 1.可以精确导出指定范围的图形要素 2.支持多格式.TIF, .EMF,.GIF, ...

  5. Google 地图 API V3 使用入门

    Google官方教程: Google 地图 API V3 使用入门 Google 地图 API V3 针对移动设备进行开发 Google 地图 API V3 之事件 Google 地图 API V3 ...

  6. 面试题目——《CC150》树与图

    面试题4.1:实现一个函数,检查二叉树是否平衡.在这个问题中,平衡树的定义如下:任意一个结点,其两颗子树的高度差不超过1. 思路:两个方法,第一种速度较快 package cc150; public ...

  7. Web编程基础--HTML、CSS、JavaScript 学习之课程作业“仿360极速浏览器新标签页”

    Web编程基础--HTML.CSS.JavaScript 学习之课程作业"仿360极速浏览器新标签页" 背景: 作为一个中专网站建设出身,之前总是做静态的HTML+CSS+DIV没 ...

  8. ImageView的常用属性

    ImageView的一些常用属性,并且这些属性都有与之对应的getter.setter方法: android:adjustViewBounds:设置ImageView是否调整自己的边界来保持所显示图片 ...

  9. 深入理解javascript原型和闭包(6)——继承

    为何用“继承”为标题,而不用“原型链”? 原型链如果解释清楚了很容易理解,不会与常用的java/C#产生混淆.而“继承”确实常用面向对象语言中最基本的概念,但是java中的继承与javascript中 ...

  10. SSH搭建

    1.首先在lib中导入ssh需要的jar包: 如图: 2.其次配置web.xml (在WEB-INF目录下) <?xml version="1.0" encoding=&qu ...