9

ネットワーク経由で送信するために、構造体を char 配列に変換しようとしています。ただし、そうすると、char配列から奇妙な出力が得られます。

#include <stdio.h>

struct x
{
   int x;
} __attribute__((packed));


int main()
{
   struct x a;
   a.x=127;
   char *b = (char *)&a;
   int i;
   for (i=0; i<4; i++)
      printf("%02x ", b[i]);
   printf("\n");
   for (i=0; i<4; i++)
      printf("%d ", b[i]);
   printf("\n");
   return 0;
}

ax のさまざまな値の出力を次に示します (gcc を使用する X86 で):
127:
7f 00 00 00
127 0 0 0

128:
ffffff80 00 00 00
-128 0 0 0

255:
フフフフフ 00 00 00
-1 0 0 0

256:
00 01 00 00
0 1 0 0

127 と 256 の値は理解できますが、128 になると数値が変わるのはなぜですか? 80 00 00 00 128 0 0 0 ではない理由

変換プロセスで何かをするのを忘れていますか、それとも整数表現について何かを忘れていますか?

*注: これは小さなテスト プログラムです。実際のプログラムでは、構造体にもっと多くの変数名があり、リトルエンディアンに変換します。
*編集:フォーマット

4

10 に答える 10

8

char は符号付きの型です。したがって、2 の補数では、0x80 は 8 ビット整数 (つまりバイト) の -128 です。

于 2009-01-11T21:02:43.313 に答える
8

xフォーマット指定子自体は、引数が でありint、数値が負であるため、 -size 値printfのゼロ以外の 4 バイトすべてを表示するには 8 文字が必要であることを示しています。修飾子は出力をゼロで埋めるように指示し、int修飾子は最小出力が 2 文字の長さであるべきであることを指示します。私が知る限り、文字列を除いて、最大幅を指定する方法はありません。02printf

さて、あなたは a のみを渡しているcharので、代わりに渡されxたフルを使用するように関数に指示します — " " パラメータintのデフォルトの引数昇格のためです。代わりに引数を単なる a として扱うように関数に指示する修飾子を...試してください。hhchar

printf("%02hhx", b[i]);
于 2009-01-11T21:12:47.910 に答える
5

構造体を char 配列であるかのように扱うことは未定義の動作です。ネットワーク経由で送信するには、代わりに適切なシリアル化を使用してください。これは C++ では面倒ですが、C ではさらに面倒ですが、読み書きするマシンから独立してアプリが動作する唯一の方法です。

http://en.wikipedia.org/wiki/Serialization#C

于 2009-01-11T21:07:25.223 に答える
1

送信するときは、次を使用してください。

(char *)&CustomPacket

変換する。私のために働きます。

于 2010-04-11T10:04:01.603 に答える
1

char は符号付きの型であるため、表示されているのは 2 つの補数表現です。(unsigned char*) にキャストすると、それが修正されます (Rowland は私を打ち負かしました)。

補足として、変更したい場合があります

for (i=0; i<4; i++) {
//...
}

for (i=0; i<sizeof(x); i++) {
//...
}
于 2009-01-11T21:04:11.500 に答える
1

char 配列の署名は問題の原因ではありません! (これは -a- 問題ですが、唯一の問題ではありません。)

整列!それがここのキーワードです。そのため、構造体を生のメモリのように扱うべきではありません。コンパイラ (およびさまざまな最適化フラグ)、オペレーティング システム、および月の満ち欠けはすべて、構造内の「隣接する」フィールドのメモリ内の実際の位置に対して奇妙で刺激的なことを行います。たとえば、char の後に int が続く構造体がある場合、構造体全体はメモリ内で 8 バイトになります。つまり、char、3 つの空白、無駄なバイト、そして int の 4 バイトです。マシンはこのようなことを好むので、構造体がメモリのページにきれいに収まるようになります。

地元の大学でマシン アーキテクチャの入門コースを受講してください。その間、適切にシリアライズします。構造体を char 配列のように扱わないでください。

于 2010-02-26T05:24:35.933 に答える
0

unsigned char 配列に変換したい場合があります。

于 2009-01-11T21:04:32.017 に答える
-1

すべてのオクテットが貴重であることを示す非常に説得力のある測定値がない限り、これを行わないでください。SMTPNNTP、または IETF によって成文化された他の多くの優れたインターネット プロトコルのいずれかのような読み取り可能な ASCII プロトコルを使用します。

本当にバイナリ形式が必要な場合でも、バイト順、基本サイズ、またはアラインメントの制約がホストごとに異なる可能性があるため、構造体のバイトを押し出すだけでは安全ではありません。明確に定義されたサイズを使用し、明確に定義されたバイト順序を使用するようにワイヤ プロトコルを設計する必要があります。実装では、次のようなマクロを使用するntohl(3)か、シフトとマスキングを使用してバイトをストリームに挿入します。何をするにしても、コードがビッグ エンディアンとリトル エンディアンの両方のホストで同じ結果を生成することを確認してください。

于 2009-01-13T02:06:17.443 に答える