6

私はこのような構造を持っています

struct packet
{
int seqnum;
char type[1];
float time1;
float pri;
float time2;
unsigned char data[512];
}

配列でパケットを受信して​​います

char buf[529];

私は seqnum,data をすべて別々に取りたい.

struct packet *pkt;
pkt=(struct packet *)buf;
printf(" %d",pkt->seqnum)
4

3 に答える 3

8

いいえ、それはうまくいかない可能性が高く、一般的にこれを行うには不適切で壊れた方法です。

そのようなものが機能するためには、コンパイラ固有の拡張機能を使用して、構造体メンバー間に目に見えないパディングがないことを確認する必要があります。たとえば、gcc では、次の__attribute__()構文を使用してこれを行います。

したがって、これは移植可能なアイデアではありません。

それについて明示し、各フィールドを展開する方がはるかに優れています。これにより、ネットワーク プロトコルで明確に定義されたエンディアンを使用する機会も得られます。これは、相互運用性のために一般的には良い考えです。

于 2013-04-15T14:05:26.800 に答える
5

いいえ、それは一般的に有効なコードではありません。最初に構造体を作成し、次にそれに memcopy を作成する必要があります。

packet p;

memcpy(&p.seqnum, buf + 0, 4);

memcpy(&p.type[0], buf + 4, 1);

memcpy(&p.time1, buf + 5, 4);

などなど。

型のサイズとエンディアンを正しく設定するには、細心の注意を払う必要があります。

于 2013-04-15T14:06:28.030 に答える
2

まず第一に、これはプラットフォームに依存するため、パフォーマンスの最適化 (キャッシュ ラインのアライメント、整数のアライメントなど) のためにコンパイラが構造体のどこにパディング バイトを挿入するかを事前に知ることはできません。もちろん、自分のプラットフォームでのみアプリを構築することを検討している場合は除きます。

とにかく、あなたの場合、どこか(ネットワーク?)からデータを取得しているように見え、データが圧縮されている可能性が非常に高いです(フィールド間にパディングバイトはありません)。

配列を構造体ポインターに本当に型キャストしたい場合でも、追加される可能性のあるパディング バイトを削除するようコンパイラーに指示できます。これは、使用するコンパイラに依存し、標準の C 実装ではないことに注意してください。gcc では、構造定義の最後に次のステートメントを追加できます。

struct my_struct {
    int blah;
    /* Blah ... */
} __attribute__((packed));

メンバーアクセス、コピーなどのパフォーマンスに影響しますのでご注意ください...

よほどの理由がない限り、絶対に使用しないでください__attribute__((packed))

もう 1 つの解決策は、自分で解析を行うことです。適切な構造体を割り当て、バッファから適切な情報を探してそのフィールドに入力するだけです。ここでは、一連のmemcpy指示でうまくいく可能性があります (Kerrek の回答を参照)。

于 2013-04-15T14:08:44.897 に答える