首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

4.位语法 | 4. Bit Syntax

4.1介绍

位语法的完整规范出现在Reference Manual

在Erlang中,Bin用于构建二进制文件和匹配二进制模式。Bin使用以下语法编写:

代码语言:javascript
复制
<<E1, E2, ... En>>

Bin是位或字节的低级序列.。bin的目的是为了能够构建二进制文件:

代码语言:javascript
复制
Bin = <<E1, E2, ... En>>

所有元素都必须绑定。或者匹配二进制:

代码语言:javascript
复制
<<E1, E2, ... En>> = Bin 

在这里,Bin被绑定,元素E1,E2……En被绑定或不绑定,如同任意匹配模式。

Bin不需要包含全部字节数。

是一个零或多位的序列,其中位数不需要被8整除。如果位数可以被8整除,那么位串也是一个二进制数。

每个元素指定位串的某个。段是二进制的一组连续位(不一定在字节边界上)。第一个元素指定了初始段,第二个元素指定了下一个段,依此类推。

下面的示例说明如何构造或匹配二进制文件,以及如何指定元素和尾。

实例

例1:二进制可以由一组常量或字符串文字构造:

代码语言:javascript
复制
Bin11 = <<1, 17, 42>>,
Bin12 = <<"abc">>

这提供了两个大小为3的二进制文件,并进行了以下评估:

  • binary_to_list(Bin11)计算为[1, 17, 42]
  • binary_to_list(Bin12)计算为[97, 98, 99]

示例2:类似地,可以从一组绑定变量构造二进制文件:

代码语言:javascript
复制
A = 1, B = 17, C = 42,
Bin2 = <<A, B, C:16>>

这给出了一个大小为4的二进制数。这里,一个大小表达式用于C指定变量的16位段Bin2

binary_to_list(Bin2)计算结果为[1, 17, 00, 42]

示例3: Bin也可以用于匹配。DE并且F是未绑定的变量,并且Bin2被绑定,如例2所示:

代码语言:javascript
复制
<<D:16, E, F/binary>> = Bin2

这给出D = 273E = 00和F绑定到1的二进制数:binary_to_list(F) = [42]

例4:以下是比较详细的匹配例子。这里Dgram绑定到IP协议版本4的IP数据报的连续字节。目标是提取数据报的头部和数据:

代码语言:javascript
复制
-define(IP_VERSION, 4).
-define(IP_MIN_HDR_LEN, 5).

DgramSize = byte_size(Dgram),
case Dgram of 
    <<?IP_VERSION:4, HLen:4, SrvcType:8, TotLen:16, 
      ID:16, Flgs:3, FragOff:13,
      TTL:8, Proto:8, HdrChkSum:16,
      SrcIP:32,
      DestIP:32, RestDgram/binary>> when HLen>=5, 4*HLen=<DgramSize ->
        OptsLen = 4*(HLen - ?IP_MIN_HDR_LEN),
        <<Opts:OptsLen/binary,Data/binary>> = RestDgram,
    ...
end.

在这里,与Opts变量相对应的段具有类型修饰符,指定Opts将绑定到二进制文件。所有其他变量的默认类型都等于无符号整数。

IP数据报头部长度可变。该长度以32位字的数量度量,并在相应的段中给出HLen。最小值HLen是5.它对应的段Opts是变量,所以如果HLen等于5,则Opts变成空的二进制。

尾变量RestDgramData绑定到二进制文件,就像所有尾变量一样。两者都可以绑定到空的二进制文件。

Dgram如果发生以下情况之一,则匹配失败:

  • 第一个4位段Dgram不等于4。
  • HLen小于5。
  • 大小Dgram小于4*HLen

4.2词汇注释

注意“ B=<<1>>”将被解释为“ B =< <1>>”,这是一个语法错误。编写表达式的正确方法是:B = <<1>>

4.3段

每个段具有以下一般语法:

Value:Size/TypeSpecifierList

SizeTypeSpecifier,或两者,可以省略。因此,允许以下变体:

  • Value
  • Value:Size
  • Value/TypeSpecifierList

缺少规格时使用默认值。默认值在中描述Defaults

Value部分是用于二进制构造的任何表达式。用于二进制匹配时,该Value部分必须是文字或变量。有关该Value部分的更多信息,请参阅Constructing Binaries and BitstringsMatching Binaries

Size段的部分乘以TypeSpecifierList(稍后描述)中的单位给出段的位数。在构造中,Size任何表达式都是一个整数。在匹配中,Size必须是常量表达式或变量。

TypeSpecifierList是一个用连字符分隔的类型说明符列表。

类型最常用的类型integerfloatbinary。请参阅Bit Syntax Expressions in the Reference Manual完整说明。签名签名规范可以是signed或者unsigned。请注意,签名仅适用于匹配。端序字节顺序规格可以是biglittle,或native。Native-endian意味着endian在加载时被解析为big-endian或little-endian,这取决于运行Erlang机器的CPU的“本地”特性。单位单位大小给出为unit:IntegerLiteral。允许的范围是1-256。它乘以Size说明符给出段的有效大小。单位大小指定没有大小的二进制段的对齐方式。

例子:

代码语言:javascript
复制
X:4/little-signed-integer-unit:8

该元素的总大小为4 * 8 = 32位,并且它包含小端顺序的有符号整数。

4.4违约

段的默认类型是整数。即使值是文字,默认类型也不依赖于该值。例如,默认的类型<<3.14>>是整数,而不是浮点型。

默认Size取决于类型。对于整数它是8.对于浮点它是64.对于二进制它是所有的二进制。在匹配中,此默认值仅对最后一个元素有效。匹配中的所有其他二进制元素必须具有大小规格。

默认单位取决于类型。对于integerfloat而且bitstring它是1.对于二进制它是8。

默认的签名是unsigned

默认的排序是big

4.5构造二进制文件和位字符串

本节介绍使用位语法构造二进制文件的规则。与构建列表或元组时不同,构造二进制文件可能会失败并产生badarg异常。

可以构建二进制文件中的零个或多个段。该表达式<<>>构造零长度二进制。

二进制中的每个段可以包含零个或多个位。类型integer和个别细分没有对齐规则float。对于没有大小的二进制和位串,单位指定对齐。由于该binary类型的默认对齐方式为8,因此二进制段的大小必须是8位的倍数,即只有整个字节。

例子:

代码语言:javascript
复制
<<Bin/binary,Bitstring/bitstring>>

该变量Bin必须包含整数个字节,因为该binary类型默认为unit:8。甲badarg如果产生异常Bin包括,例如,17位。

Bitstring变量可以包含任意数量的位,例如0,1,8,11,17,42等。这是因为unitbitstrings 的默认值为1。

为了清楚起见,建议不要更改二进制文件的单位大小。相反,binary在需要字节对齐和bitstring需要位对齐时使用。

以下示例成功构造了一个7位的位串,前提是X和Y都是整数:

代码语言:javascript
复制
<<X:1,Y:6>>

如前所述,段具有以下一般语法:

Value:Size/TypeSpecifierList

当构造的二进制文件,Value并且Size可以是任何的Erlang表达。但是,出于语法原因,如果表达式包含超过单个文字或变量的任何内容Value,则Size必须将它们括在括号中。以下给出了一个编译器语法错误:

代码语言:javascript
复制
<<X+1:8>>

必须将该表达式重写为下列内容,以供编译器接受:

代码语言:javascript
复制
<<(X+1):8>>

包括文字字符串

可以编写文字字符串而不是元素:

代码语言:javascript
复制
<<"hello">>

这是用于下列方面的语法糖:

代码语言:javascript
复制
<<$h,$e,$l,$l,$o>>

4.6匹配二进制文件

本节使用位语法描述匹配二进制文件的规则。

二进制模式中可以有零个或多个段。二元模式可以发生在允许模式的地方,包括其他模式。二进制模式不能嵌套。该模式<<>>匹配零长度二进制。

二进制中的每个段可以包含零个或多个位。段的类型binary必须能够被8整除(如果单元大小已更改,则可以被单元大小整除)。一段类型bitstring的大小没有限制。

如前所述,段具有以下一般语法:

Value:Size/TypeSpecifierList

匹配Value时,值必须是变量或整数,或浮点文字。表达式是不允许的。

Size必须是整数文本,或以前绑定的变量。不允许采取以下措施:

代码语言:javascript
复制
foo(N, <<X:N,T/binary>>) ->
   {X,T}.

这两个事件N没有关系。编译器会抱怨Nsize字段没有绑定。

编写这个例子的正确方法如下:

代码语言:javascript
复制
foo(N, Bin) ->
   <<X:N,T/binary>> = Bin,
   {X,T}.

获取二进制或位字符串的其余部分。

要匹配二进制文件的其余部分,请指定一个不含大小的二进制字段:

代码语言:javascript
复制
foo(<<A:8,Rest/binary>>) ->

尾巴的大小必须被8整除。

要匹配比特串的其余部分,请指定一个没有大小的字段:

代码语言:javascript
复制
foo(<<A:8,Rest/bitstring>>) ->

尾部的位数没有限制。

4.7添加到二进制文件

以一种有效的方式附加到二进制文件中可以这样做:

代码语言:javascript
复制
triples_to_bin(T) ->
    triples_to_bin(T, <<>>).

triples_to_bin([{X,Y,Z} | T], Acc) ->
    triples_to_bin(T, <<Acc/binary,X:32,Y:32,Z:32>>);
triples_to_bin([], Acc) -> 
    Acc.

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com