4.位语法 | 4. Bit Syntax
4 位语法
4.1介绍
位语法的完整规范出现在Reference Manual
。
在Erlang中,Bin用于构建二进制文件和匹配二进制模式。Bin使用以下语法编写:
<<E1, E2, ... En>>
Bin是位或字节的低级序列.。bin的目的是为了能够构建二进制文件:
Bin = <<E1, E2, ... En>>
所有元素都必须绑定。或者匹配二进制:
<<E1, E2, ... En>> = Bin
在这里,Bin
被绑定,元素E1,E2……En
被绑定或不绑定,如同任意匹配模式。
Bin不需要包含全部字节数。
位串
是一个零或多位的序列,其中位数不需要被8整除。如果位数可以被8整除,那么位串
也是一个二进制数。
每个元素指定位串的某个段
。段
是二进制的一组连续位(不一定在字节边界上)。第一个元素指定了初始段
,第二个元素指定了下一个段
,依此类推。
下面的示例说明如何构造或匹配二进制文件,以及如何指定元素和尾。
实例
例1:
二进制可以由一组常量或字符串文字构造:
Bin11 = <<1, 17, 42>>,
Bin12 = <<"abc">>
这提供了两个大小为3的二进制文件,并进行了以下评估:
binary_to_list(Bin11)
计算为[1, 17, 42]
。
binary_to_list(Bin12)
计算为[97, 98, 99]
。
示例2:
类似地,可以从一组绑定变量构造二进制文件:
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也可以用于匹配。D
,E
并且F
是未绑定的变量,并且Bin2
被绑定,如例2所示:
<<D:16, E, F/binary>> = Bin2
这给出D = 273
,E = 00
和F绑定到1的二进制数:binary_to_list(F) = [42]
。
例4:
以下是比较详细的匹配例子。这里Dgram
绑定到IP协议版本4的IP数据报的连续字节。目标是提取数据报的头部和数据:
-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
变成空的二进制。
尾变量RestDgram
和Data
绑定到二进制文件,就像所有尾变量一样。两者都可以绑定到空的二进制文件。
Dgram
如果发生以下情况之一,则匹配失败:
- 第一个4位段
Dgram
不等于4。
HLen
小于5。
- 大小
Dgram
小于4*HLen
。
4.2词汇注释
注意“ B=<<1>>”将被解释为“ B =< <1>>”,这是一个语法错误。编写表达式的正确方法是:B = <<1>>。
4.3段
每个段具有以下一般语法:
Value:Size/TypeSpecifierList
Size
或TypeSpecifier
,或两者,可以省略。因此,允许以下变体:
Value
Value:Size
Value/TypeSpecifierList
缺少规格时使用默认值。默认值在中描述Defaults
。
Value
部分是用于二进制构造的任何表达式。用于二进制匹配时,该Value
部分必须是文字或变量。有关该Value
部分的更多信息,请参阅Constructing Binaries and Bitstrings
和Matching Binaries
。
Size
段的部分乘以TypeSpecifierList
(稍后描述)中的单位给出段的位数。在构造中,Size
任何表达式都是一个整数。在匹配中,Size
必须是常量表达式或变量。
TypeSpecifierList
是一个用连字符分隔的类型说明符列表。
类型
最常用的类型
integer
,float
和binary
。请参阅Bit Syntax Expressions in the Reference Manual
完整说明。签名
签名
规范可以是signed
或者unsigned
。请注意,签名
仅适用于匹配。端序
字节顺序规格可以是big
,little
,或native
。Native-endian意味着endian在加载时被解析为big
-endian或little
-endian,这取决于运行Erlang机器的CPU的“本地”特性。单位
单位
大小给出为unit:IntegerLiteral
。允许的范围是1-256。它乘以Size
说明符给出段的有效大小。单位
大小指定没有大小的二进制段的对齐方式。
例子:
X:4/little-signed-integer-unit:8
该元素的总大小为4 * 8 = 32位,并且它包含小端顺序的有符号整数。
4.4违约
段的默认类型是整数。即使值是文字,默认类型也不依赖于该值。例如,默认的类型<<3.14>>是整数,而不是浮点型。
默认Size
取决于类型。对于整数它是8.对于浮点它是64.对于二进制它是所有的二进制。在匹配中,此默认值仅对最后一个元素有效。匹配中的所有其他二进制元素必须具有大小规格。
默认单位取决于类型。对于integer
,float
而且bitstring
它是1.对于二进制它是8。
默认的签名是unsigned
。
默认的排序是big
。
4.5构造二进制文件和位字符串
本节介绍使用位语法构造二进制文件的规则。与构建列表或元组时不同,构造二进制文件可能会失败并产生badarg
异常。
可以构建二进制文件中的零个或多个段。该表达式<<>>构造零长度二进制。
二进制中的每个段可以包含零个或多个位。类型integer
和个别细分没有对齐规则float
。对于没有大小的二进制和位串,单位指定对齐。由于该binary
类型的默认对齐方式为8,因此二进制段的大小必须是8位的倍数,即只有整个字节。
例子:
<<Bin/binary,Bitstring/bitstring>>
该变量Bin
必须包含整数个字节,因为该binary
类型默认为unit:8
。甲badarg
如果产生异常Bin
包括,例如,17位。
Bitstring
变量可以包含任意数量的位,例如0,1,8,11,17,42等。这是因为unit
bitstrings 的默认值为1。
为了清楚起见,建议不要更改二进制文件的单位大小。相反,binary
在需要字节对齐和bitstring
需要位对齐时使用。
以下示例成功构造了一个7位的位串,前提是X和Y都是整数:
<<X:1,Y:6>>
如前所述,段具有以下一般语法:
Value:Size/TypeSpecifierList
当构造的二进制文件,Value
并且Size
可以是任何的Erlang表达。但是,出于语法原因,如果表达式包含超过单个文字或变量的任何内容Value
,则Size
必须将它们括在括号中。以下给出了一个编译器语法错误:
<<X+1:8>>
必须将该表达式重写为下列内容,以供编译器接受:
<<(X+1):8>>
包括文字字符串
可以编写文字字符串而不是元素:
<<"hello">>
这是用于下列方面的语法糖:
<<$h,$e,$l,$l,$o>>
4.6匹配二进制文件
本节使用位语法描述匹配二进制文件的规则。
二进制模式中可以有零个或多个段。二元模式可以发生在允许模式的地方,包括其他模式。二进制模式不能嵌套。该模式<<>>匹配零长度二进制。
二进制中的每个段可以包含零个或多个位。段的类型binary
必须能够被8整除(如果单元大小已更改,则可以被单元大小整除)。一段类型bitstring
的大小没有限制。
如前所述,段具有以下一般语法:
Value:Size/TypeSpecifierList
匹配Value
时,值必须是变量或整数,或浮点文字。表达式是不允许的。
Size
必须是整数文本,或以前绑定的变量。不允许采取以下措施:
foo(N, <<X:N,T/binary>>) ->
{X,T}.
这两个事件N
没有关系。编译器会抱怨N
size字段没有绑定。
编写这个例子的正确方法如下:
foo(N, Bin) ->
<<X:N,T/binary>> = Bin,
{X,T}.
获取二进制或位字符串的其余部分。
要匹配二进制文件的其余部分,请指定一个不含大小的二进制字段:
foo(<<A:8,Rest/binary>>) ->
尾巴的大小必须被8整除。
要匹配比特串的其余部分,请指定一个没有大小的字段:
foo(<<A:8,Rest/bitstring>>) ->
尾部的位数没有限制。
4.7添加到二进制文件
以一种有效的方式附加到二进制文件中可以这样做:
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.