5

Rubyではなぜ配列が必要なのPackingですか?directiveそのようなパッキングを行うのにどのように役立ちますか?

コンソールでコードを実行して、配列パッキングでディレクティブがどのように表示されるかを確認しましたが、出力は各ディレクティブとほぼ同じです。それでは、コアではそれらがどのように異なるのでしょうか?

irb(main):003:0> n = [ 65, 66, 67 ]
=> [65, 66, 67]
irb(main):004:0> n.pack("ccc")
=> "ABC"
irb(main):005:0> n.pack("C")
=> "A"
irb(main):006:0> n.pack("CCC")
=> "ABC"
irb(main):007:0> n.pack("qqq")
=> "A\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x00\
x00\x00\x00"
irb(main):008:0> n.pack("QQQ")
=> "A\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x00\
x00\x00\x00"
irb(main):009:0> n.pack("SSS")
=> "A\x00B\x00C\x00"
irb(main):010:0> n.pack("sss")
=> "A\x00B\x00C\x00"
irb(main):011:0>

n.pack("SSS") and n.pack("sss");n.pack("ccc") and n.pack("CCC"); n.pack("qqq") and n.pack("QQQ")これで、同じ出力を提供するコンソールから確認できます。では、違いはどこにありますか?

また、ドキュメントでは、実際のプログラムで各ディレクティブがどのように機能するかについての例も少し取り上げていません。また、以下のディレクティブをテストする方法がわからないため、それらと混同していますか?それらを含む小さなコードも私に役立ちます:

  • S_, S!
  • S> L> Q>
  • S!< I!<
  • L_, L!
4

1 に答える 1

17

あなたは、コンピューターが数値をメモリに格納する方法の基本原則について質問しています。たとえば、これらを参照して詳細を確認できます。

http://en.wikipedia.org/wiki/Computer_number_format#Binary_Number_Representation
http://en.wikipedia.org/wiki/Signed_number_representations

例として、 と の違いを取り上げSますs。どちらも 16 ビット数値のパックとアンパックに使用されますが、1 つは符号付き整数用で、もう 1 つは符号なし整数用です。これは、文字列を元の整数にアンパックしたい場合に重要な意味を持ちます。

S: 16 ビットの符号なしは、0 ~ 65535 (0 ~ (2^16-1)) の数値を意味します。 : 16 ビットの符号
s付き整数 -32768 ~ 32767 (-(2^15) ~ (2^15-1)) (1符号に使用されるビット)

違いは次のとおりです。

# S = unsigned: you cannot pack/unpack negative numbers
> [-1, 65535, 32767, 32768].pack('SSSS').unpack('SSSS')
=> [65535, 65535, 32767, 32768]   

# s = signed: you cannot pack/unpack numbers outside range -32768 - 32767
> [-1, 65535, 32767, 32768].pack('ssss').unpack('ssss')
=> [-1, -1, 32767, -32768]

質問を理解するには、コンピューターのメモリで数値がどのように表現されるかを知る必要があります。符号付き数値は符号を表すために 1 ビットを使用しますが、符号なし数値はこの余分なビットを必要としませんが、負の数値を表すことはできません。

これは、コンピューター メモリ内で数値を 2 進数として表す方法の基本です。

たとえば、パッキングが必要な理由は、あるコンピューターから別のコンピューターに数値をバイトストリームとして送信する必要がある場合です (ネットワーク接続など)。ストリーム経由で送信するには、整数をバイトにパックする必要があります。もう 1 つのオプションは、数値を文字列として送信することです。次に、パックとアンパックの代わりに、両端で文字列としてエンコードおよびデコードします。

または、Ruby からシステム ライブラリの C 関数を呼び出す必要があるとします。C で記述されたシステム ライブラリは、基本的な整数 (int、uint、long、short など) と C 構造体 (struct) で動作します。そのようなシステム メソッドを呼び出す前に、Ruby 整数をシステム整数または C 構造体に変換する必要があります。そのような場合pack、 andunpackを使用して、そのようなメソッドをインターフェースすることができます。


追加のディレクティブに関しては、パックされたバイト シーケンスを表現する方法のエンディアンを扱います。エンディアンの意味とその仕組みについては、こちらを参照してください。

http://en.wikipedia.org/wiki/エンディアンネス

簡単に言えば、整数をバイトに変換する順序をパッキング方法に伝えるだけです。

# Big endian
> [34567].pack('S>').bytes.map(&:to_i)
=> [135, 7]   
# 34567 = (135 * 2^8) + 7

# Little endian
> [34567].pack('S<').bytes.map(&:to_i)
=> [7, 135]   
# 34567 = 7 + (135 * 2^8)
于 2013-01-12T14:18:14.270 に答える