erlang bit语法

来源:互联网 发布:超星软件打不开 编辑:程序博客网 时间:2024/06/08 00:49

Erlang的比特语法(Erlang Bit Syntax)提供了一种方法来匹配二进制数据,这使得Erlang二进制对象在某种程度上等同于其他Erlang对象,如元组和列表。也因为其快速高效,使得在Erlang中,二进制对象被广泛使用,尤其是在协议编程方面。(官方文档)

Erlang的比特语法表达式:

[plain] view plaincopy
  1. <<>>   
  2. <<E1,...,En>>  

每个元素Ei指定了一段二进制串(bit string)。每个元素Ei都是一个值,后面可以带有可选参数Size、TypeSpecifierList

[plain] view plaincopy
  1. Ei = Value |  
  2.      Value:Size |  
  3.     Value/TypeSpecifierList |  
  4.     Value:Size/TypeSpecifierList  

Size表示前一个Value数据存储的位数,默认是8位,也就是一个字节。

TypeSpecifierList可以是以下几种类型及其组合,组合以 - 相连

Type = integer | float | binary | bytes |bitstring | bits | utf8 | utf16 | utf32

       默认值是integer。bytes是binary的简写,bits是bitsring的简写

Signedness = signed | unsigned

       只有当type为integer时有用,默认是unsigned

Endianness = big | little | native

       当type为integer,utf16,utf32,float有用,默认是big

Unit = unit:IntegerLiteral

       有效范围是1-256,integer、float和bitstring默认是1,binary默认是8

例如:

[plain] view plaincopy
  1. -define( UINT, 32/unsigned-little-integer).  
  2. -define( INT, 32/signed-little-integer).  
  3. -define( USHORT, 16/unsigned-little-integer).  
  4. -define( SHORT, 16/signed-little-integer).  
  5. -define( UBYTE, 8/unsigned-little-integer).  
  6. -define( BYTE, 8/signed-little-integer).  
  7. -define( CHAR, 1/binary-unit:8).  

在官方文档找到以下一段代码:

1> Bin1 = <<1,17,42>>.<<1,17,42>>2> Bin2 = <<"abc">>.<<97,98,99>>3> Bin3 = <<1,17,42:16>>.<<1,17,0,42>>4> <<A,B,C:16>> = <<1,17,42:16>>.<<1,17,0,42>>5> C.426> <<D:16,E,F>> = <<1,17,42:16>>.<<1,17,0,42>>7> D.2738> F.429> <<G,H/binary>> = <<1,17,42:16>>.<<1,17,0,42>>10> H.<<17,0,42>>11> <<G,H/bitstring>> = <<1,17,42:12>>.<<1,17,2,10:4>>12> H.<<17,2,10:4>>

 

例子说明:

1、例子1和2:从一组常量或一个字符串来构造二进制对象

1> Bin1 = <<1,17,42>>.2> Bin2 = <<"abc">>.

以上生成的二进制大小为3。binary_to_list(Bin1) 得到 [1, 17, 42],binary_to_list(Bin2) 得到[97, 98, 99]。数字常量是在0-255之间的整数,用8位存储,如果超过这个范围后面加:Size来说明,如<<256:16>>。字符则会转化为ASCII码。

 

2、例子3:从一组限定边界的变量来构造二进制对象

3> Bin3 = <<1,17,42:16>>.

以上生成的二进制大小为4。

上面,我们给42指定了16位的大小来储存,所以在内存中的数据为0000 0000 0010 1010,这样构成出来的对象就是<<0, 42>>


3、例子4、6:按照某种形式匹配二进制对象

4> <<A,B,C:16>> = <<1,17,42:16>>.6> <<D:16,E,F>> = <<1,17,42:16>>.

例子4很好理解,这里说一下例子6吧,为何D会得到273的结果?

<<1,17,42:16>>生成的二进制数据前面说过了,为<<1,17,0,42>>

D:16表示匹配内存中16位的二进制数据,所以的到就是<<1,17>>在内存中的数据,为0000 0001 0001 0001,结果就是256 + 16 + 1,也就是273


4、例子11:也是从一组限定边界的变量来构造二进制对象,和例子3不同的是大小不是8的倍数。

<<1,17,42:12>>.

上面,我们给42指定了12位的大小来存储,所以在内存中的数据为0000 0010 1010,

这样构造出来的对象就是<<2,10:4>>

在erlang 二进制中,对象默认以8位为一个单位来表示,不足就向后面借位,比如:<<42:12,1,17>>生成的二进制对象是<<2,160,17,1:4>>,其实两者表达的是一段相同的二进制数据。


注意:

 "B=<<1>>" 在erlang中被解释成 "B =< <1>>",这会引起一个语法错误“syntax error before: '<'”。正确的做法是写成 "B = <<1>>" 


binary与bitstring的区别?

erlang文档有说明:

A bitstring is a sequence of zero or more bits, where the number of bits does not need to be divisible by 8. If the number of bits is divisible by 8, the bitstring is also a binary.

就是说,binary也是bitstring的一种,当二进制串大小能被8整除,就是binary


什么情况下会区分?

如模式匹配:

[plain] view plaincopy
  1. foo(<<A:8,Rest/binary>>) ->  
  2.     {binary, A, Rest};  
  3. foo(<<A:8,Rest/bitstring>>) ->  
  4.     {bitstring, A, Rest}.  

  1. 位串(bitstring)是由一些有比特(bit,理解为‘位’)组成,不要求包含的比特数量能够整除8,如果恰好能够整除8的话,那么这个位串就是个binary。

  2. 位串中的每一个位都位于确定的一个段中,一个段由一串连续的位组成(段之间没有界限),如首位是第一个段,紧接着就是第二个段。

  3. 下面的例子演示了二进制数据的构造,匹配,还有如何获取和使用二进制数据中的元素。

  4. 1. 一些简单的例子
  5. 例一
  6.     一个二进制数据由一组常量或者简单字符串构成
  7. Bin11 = <<1, 17, 42>>,
  8. Bin12 = <<"abc">>
  9. 产生的二进制数据大小为3,binary_to_list(Bin11)计算结果是[1, 17, 42], binary_to_list(Bin22)计算结果是[97, 98, 99].

  10. 例二
  11.     类似的,一个二进制数据也可以由一组已绑定的变量构成
  12. A = 1,B = 17, C= 42,
  13. Bin2 = <<A,B, C:16>>
  14. 产生的二进制数据大小为4,binary_to_list(Bin2)计算结果是[1, 17, 0, 42]。这里C使用了尺寸表达式(size expression),指定了C这个段在二进制数据中占用16位,也就是两个单位长度。

  15. 例三
  16.     二进制数据也可以进行匹配操作。假设D,E,F是自由变量,Bin2为例二中的变量:
  17.  <<D:16, E, F/binary>>= Bin2
  18. 结果 D = 273,(因为D包含了A,B两个段,二进制转换为10进制之后的结果),E= 0,F = 42(这里在我的机器上是<<*>>,我的erlang版本比文档上的版本新)

  19. 2.注意
  20.     语法上应该要注意的地方, "B=<<1>>" 这样的写法会被erlang编译器理解为"B =< <1>>" ,这样就会产生语法错误。正确的写法应该是 "B = <<1>>"

  21. 3.二进制数据各个部分介绍
  22.     位串中,每一个段都遵循通用的语法格式,如下:
  23. Value:Size/TypeSpecifierList 值:大小/类型
  24. 因为Size和TypeSpeciferList不是必须指明的,所以在书写的时候它们可以省略,下面的格式是正确的:
  25. Value
  26. Value:Size
  27. Value/TypeSpecifierList
  28. 当没有指明使用什么规范时,就使用默认值(默认规范,也可以理解为默认语法约定)。默认值会在下面解释
  29. 在构造二进制数据结构的时候,Value可以是任何表达式;在进行二进制的匹配操作时,Value必须是一个普通的单词(literal)或者变量。
  30. Size 指明该段占多少位,要是指明了 TypeSpecifierList (类型),Size表示的多少个单位长度,size必须是整数。
  31. TypeSpecifierList 由 ‘-’ 隔开的一组属性组成,可以由四个部分构成:
  32.     Type 类型,可以是 Integer, Float, Binary
  33.     Signedness 规定是无符号还是有符号
  34.     Endianness 规定字节存储序列
  35.     Unit 单位长度,必须能被Size 整除
  36. 如:
  37.     X:4/little-signed-integer-unit:8
  38.     X 的总大小是 4 * 8 = 32 bit啰

  39. 4.默认(约定)
  40.     二进制中每个段的数据类型默认是整型,默认的类型不依赖于值,即便值是一个单词。
  41. 类似的, "<<3.14>>" 的类型也是整型,不是浮点型。
  42.   默认的大小(Size)由类型决定,整型是8,浮点是64,如果是binary类型的话就是该binary的整个长度。在匹配操作中,只有最后一段数据使用默认大小才是合法的,其他位置的数据段必须指定大小。
  43.   默认的单位长度,整型和浮点都是1,binary是8.
  44.   默认是无符号
  45.   默认的字节序列是大头排列

  46. 5.构造一个binary 和 位串(bitstring)
  47.     构造二进制的语法和创建列表和元组不一样,如果参数错误的话,会爆出 “badarg”的错误。
  48.     一个二进制可以由一个或多个段构成,0个段 “<<>>”表示大小为零的二进制数据(很多时候,我们会发空     的二进制作为触发没个事件的信号)。
  49.    <<Bin/binary,Bitstring/bitstring>>
  50.     这样一个数据,Bin的大小一定是8比特的整数倍,而Bitstring的大小一定是1的整数倍。
  51.     下面的数据:
  52.     <<X:1, Y:6>>
  53.     可以成功构造一个大小为7bit的位串,特别的提出一点:
  54.     <<X+1:8>> 是错误的,应该写作:
  55.     <<(X+1):8>>
  56.     <<"hello">> 等价于<<$h,$e,$l,$l,$o>>,前者在语法上比后者更加便利(语法糖)
  57. 6.二进制数据的匹配操作
  58.     匹配操作的时候,记住Size一定是一个整数或者绑定的变量(值为整数),如
  59.     foo(N,<<X:N,T/binary>>)->
  60.     {X,T}.
  61.     这样是错误的,因为在编译的时候,N作为Size还没有绑定。
  62.     正确的做法:
  63.     foo(N, Bin)->
  64.        <<X:N,T/binary>>= Bin,
  65.        {X,T}.
  66. 7.获取一个二进制和位串的剩余部分
  67.     foo(<<A:8,Rest/binary>>)->
  68.        Rest的大小一定能整除8
  69.     foo(<<A:8,Rest/bitstring>>)->
  70.        Rest的大小没有严格限制了

  71. 8.位串解析(Bit String Comprehensions)
  72.     位串解析类似列表解析,是一种非常高效的产生新的位串的方法,一般语法如下:
  73.     << BitString|| Qualifier1,...,QualifierN>>
  74.     BitString一个合法的位串表达式,Qualifier是位串生成器或者过滤器
  75.     一般的生成器(如列表解析里面),通常写作:
  76.       Pattern <- ListExpr.
  77.     而位串生成器写作:
  78.      BitstringPattern <= BitStringExpr.
  79.     当然了,这里BitStringExpr 肯定一个合法的位串表达式
  80.     
  81.     过滤器是一个返回true或false的表达式
  82.     具体的例子:
  83.     << << (X*2)>> || <<X>><= << 1,2,3>> >>.
  84.     <<2,4,6>>


0 0
原创粉丝点击