13

私はこれについて大まかにそこに物事があることを知っています..しかし、私の脳は傷つき、これを機能させるものは何も見つかりません.

Unix ソケット経由で 16 ビットの符号なし整数を送信しようとしています。そのためには、uint16_t を 2 つの文字に変換する必要があります。次に、接続の反対側でそれらを読み取り、それをいずれかの文字列に戻す必要があります。 unsigned int または uint16_t、その時点で、2 バイトを使用するか 4 バイトを使用するかは問題ではありません (64 ビットを実行しているため、unsigned int を使用できません:)

私はこれをCでやっていますbtw

ありがとう

4

4 に答える 4

37

マスクとシフトを使用してバイトに分割しないのはなぜですか?

 uint16_t value = 12345;
 char lo = value & 0xFF;
 char hi = value >> 8;

(編集)

もう一方の端では、逆に組み立てます。

 uint16_t value = lo | uint16_t(hi) << 8;

頭のてっぺんから、そのキャストが必要かどうかわかりません。

于 2012-11-07T22:10:15.233 に答える
3
char* pUint16 = (char*)&u16;

つまり、uint16_tのアドレスをキャストします。

char c16[2];
uint16_t ui16 = 0xdead;
memcpy( c16, ui16, 2 );

c16には、u16の2バイトが含まれるようになりました。遠端では、プロセスを逆にするだけです。

char* pC16 = /*blah*/
uint16_t ui16;
memcpy( &ui16, pC16, 2 );

興味深いことに、memcpyの呼び出しがありますが、サイズが固定されているため、ほぼすべてのコンパイラがそれを最適化します。

Steven sudtが指摘しているように、ビッグエンディアンの問題が発生する可能性があります。これを回避するには、htons(host-to-network short)関数を使用できます。

uint16_t ui16correct = htons( 0xdead );

遠端ではntohs(ネットワークからホストへのショート)を使用します

uint16_t ui16correct = ntohs( ui16 );

リトルエンディアンのマシンでは、これによりショートがビッグエンディアンに変換され、遠端でビッグエンディアンから変換されます。ビッグエンディアンのマシンでは、2つの関数は何もしません。

もちろん、ネットワーク上の両方のマシンのアーキテクチャが同じエンディアンを使用していることがわかっている場合は、この手順を回避できます。

32ビット整数を処理するためにntohlとhtonlを検索します。ほとんどのプラットフォームは、64ビットのntohllとhtonllもサポートしています。

于 2012-11-07T22:08:59.767 に答える
2

ビットマスクとシフト演算子を使用する必要があるようです。

16 ビットの数値を 2 つの 8 ビットの数値に分割するには:

  • ビットごとの AND 演算子 (C では &) を使用して下位 8 ビットをマスクし、上位 8 ビットがすべて 0 になるようにしてから、その結果を 1 つの文字に割り当てます。
  • 右シフト演算子 (C では >>) を使用して上位 8 ビットを右にシフトし、上位 8 ビットのみを残して下位 8 ビットをすべて整数から押し出し、それを別の文字に割り当てます。

次に、接続を介してこれらの 2 つの文字を送信するときは、逆のことを行います。これまで上位 8 ビットだったものを 8 ビット左にシフトし、ビットごとの OR を使用してそれを他の 8 ビットと結合します。

于 2012-11-07T22:11:32.770 に答える
1

基本的に、ソケット経由で 2 バイトを送信しています。エンディアンや符号などに関係なく、ソケットが知る必要があるのはこれだけです... uint16 を 2 バイトに分解し、ソケット経由で送信するだけです。

char byte0 = u16 & 0xFF;
char byte1 = u16 >> 8;

もう一方の端では、逆の方法で変換を行います

于 2012-11-07T22:14:01.923 に答える