Shell represents binary

眉间皱痕 提交于 2019-12-25 05:24:54

问题


I have following statement

iex(5)> a = <<3>>
<<3>>
iex(6)> b = <<a::binary>>
<<3>>

First line, I created a binary with value 3. On third line I want that the shell shows me 00000011 not 3. I know it does not make sense first the create a binary(1.line) then convert to binary again. But I was expecting that shell shows me 00000011 instead of 3.

When binary as float like

iex(7)> a = << 5.3 :: float  >>
<<64, 21, 51, 51, 51, 51, 51, 51>>

I do not understand, why it shows me this numbers?


回答1:


Binary is a sequence of bytes in memory. The printed representation matches this definition. Every number in printed output is between 0 and 255 (those numbers can represent all possible values of byte).

Binaries are cool and easy way to parse and encode protocols or other messages to be send over the network to external systems. For example this piece of code parses ip protocol:

<< protocol_version :: size(4),
   size_in_words :: size(4),
   tos :: size(8),
   total_length :: size(16),
   identifier :: size(16),
   flags :: size(3),
   fragment_offs :: size(13),
   ttl :: size(8),
   protocol :: size(8),
   header_checksum :: size(16),
   src_ip :: size(32),
   dst_ip :: size(32),
   options :: size(32),
   data :: binary >> = bits

You can match on different parts of binary. size is specified in bits. Last part can be without size, BUT it needs to have size divisible by 8 (it has to be n full bytes).

Less complicated example might be number 128, which is 10000000 in binary.

iex(1)> bin = <<128>>
<<128>>
iex(2)> <<a::size(2), b::size(6)>> = bin
<<128>>
iex(3)> a # a matched bits 10, which is 2
2
iex(4)> b # b matched bits 000000 which is 0
0

The same syntax can be used to create binaries from parts. Lets reuse variables a and b, but put them in different places.

iex(5)> anotherbin = <<a::size(5), b::size(3)>>
<<16>>

Now the first part is 00010 and second part is 000, which gives 00010000, which is 16. Another thing is that you can create binaries from other things than integers like floats, so

iex(6)> a = << 5.3 :: float  >>
<<64, 21, 51, 51, 51, 51, 51, 51>>

creates another binary that has the float value encoded. You can now send it over the network and decode it on the other side. So it is opposite to what you thought. It is not binary as a float, but float as a binary.

To actually see binary representation of stuff try using to_string methods from different modules. They have optional argument that is base in which you want to print the output.

iex(7)> Integer.to_string(128, 2)
"10000000"

There is one more catch. Strings in Elixir are actually binaries. The shell checks if all bytes are printable characters. If yes, then prints them as a string

iex(20)> <<100>>
"d"

You can force IO.inspect to print binaries as list of bytes or strings if you want:

iex(29)> IO.inspect <<100>>, [{:binaries, :as_binaries}]
<<100>> #this is what IO.inspect printed
"d"     #this is a return value, which is the same, but printed as string

If you force non printable characters to be interpreted as strings, they will be escaped:

iex(31)> IO.inspect <<2>>, [{:binaries, :as_strings}]
"\x02" #this is what IO.inspect printed
<<2>>  #return value printed by shell


来源:https://stackoverflow.com/questions/36094791/shell-represents-binary

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!