博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ 的二进制语法与语义
阅读量:5248 次
发布时间:2019-06-14

本文共 3282 字,大约阅读时间需要 10 分钟。

/* 转载请注明出处: */

二进制的语法

  C/C++ 默认数字使用十进制,八进制使用前缀 0, 十六进制使用前缀 0x 或 0X,二进制常数的提议被否决(引用   的 6.4.4.1 章节字段 "A proposal to add binary constants was rejected due to lack of precedent and insufficient utility."),一直没有二进制的表示方法,  ,其实很多编译器都有这个扩展的,只是标准委员会一直没采纳。直到 才引进,可谓姗姗来迟啊。这种二进制语义  也早些时候引入, 也引入,Python 为了避免十进制与八进制的混淆,一律用字母前缀,不分大小写,0b 为二进制,0o 为八进制,ox 为十六进制。Python2 升到 Python3 时果断丢弃了原来的八进制语义(也就是在 C/C++/Java 里面有 0 前缀的八进制的语义)。
 
表示方法
1. 下面每行语句表达语义相同,只是选用不同的进制数表示。
int i = 0b101010;  // binaryint i = 052;  // octalint i = 42;  // decimalint i = 0x2a;  // hexadecimal

 

2. 使用 strtol/strtoll/strtoq 函数,可以将一个字符串转换成整数,base 取 2 表示转换成二进制数。
#include <stdlib.h>
long int (const char *nptr, char **endptr, int base);
long long int (const char *nptr, char **endptr, int base);

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

#include 
#include
#include
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
(raw); do { begin = end; long int byte = strtol(begin, &end, 2/*base*/); putchar(static_cast
(byte)); }while(begin != end); return 0;}

 

3.  也可以使用 STL 里的 完成,不仅可以用数字,也可以用其他字符表示 0/1,这个比方法 2 更强大。这种方法我在做 解密题用到过,将 A/B 字符映射成 0/1 数字。
// unsigned long long constructorstd::bitset<8> (42);// string constructorstd::string bits = "110010";std::bitset<8> binary(bits);  // [0,0,1,1,0,0,1,0]// string constructor using custom zero/one digitsstd::string bacon = "ABABB";std::bitset<5> m(bacon, 0, std::string::npos, 'A', 'B'); // [0,1,0,1,1]
 
4. 可以使用 boost 库的 , 可以每隔开几个数字一写,在表示很大的数时很方便阅读。
int value1 = BOOST_BINARY( 100 111000 01 1 110 );unsigned long value2 = BOOST_BINARY_UL( 100 001 ); // unsigned longlong long value3 = BOOST_BINARY_LL( 11 000 ); // long long if supported

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

5. 如果不是一项工程,而是简短的程序,可以利用 C++ 的模板模拟二进制语义。
template
struct binary{ enum { value = (N%10) + binary
::value*2 };};template<>struct binary{ enum { value = 0 };}
 
int value = static_cast<int>(binary<101010>::value);
上面的代码中, enum 是为了让变量在编译期获取结果,没有用整型。还有一个问题是如果数的开头有 0,结果可不妙。整个数被当成了八进制而不是十进制数解析,很容易滋生 bug。比较好的解决方法是数字经常以 0 开头(或添加断言强制),将十进制换成八进制。
 
 
// need to enable C++11 flagtemplate
struct binary{  constexpr static int value = binary
::value + N%8;}; template<>struct binary<0>{  constexpr static int value = 0;}

 

6.  采用用户自定字面值( ),注意这个是 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);

 

 
 

转载于:https://www.cnblogs.com/Martinium/p/binary_literal.html

你可能感兴趣的文章
观察者模式
查看>>
电商网站的宕机案例分析
查看>>
查看Linux端口的占用及连接情况
查看>>
让IE浏览器支持CSS3圆角属性的方法
查看>>
NetScaler VPX在Azure上的部署(二)
查看>>
巡风源码阅读与分析---nascan.py
查看>>
[CODEVS 3037] 线段覆盖 5
查看>>
LiveBinding应用 dataBind 数据绑定
查看>>
scala操作HBase2.0
查看>>
Linux重定向: > 和 &> 区别
查看>>
ppt打不出中文
查看>>
nginx修改内核参数
查看>>
【欧拉函数模板题】最大公约数
查看>>
IOS做天气预报
查看>>
C 筛选法找素数
查看>>
TCP为什么需要3次握手与4次挥手(转载)
查看>>
IOC容器
查看>>
计算机网络(谢希仁版)——第三章回顾(2)
查看>>
jQuery1.0图片截览
查看>>
Css实现元素的垂直居中
查看>>