1

ポインター演算を使用してパケット構造体からいくつかのフィールドを取得したいのですが、以下のコードの何が問題になっていますか?
最初の条件では、パケットの先頭から 4 バイト (2 つの短いフィールド) に移動すると tLow を取得すると思います。しかし、期待値が得られません。私の考えは間違っていますか?

struct packet{  
      short len;
      short field;
      int tLow;
      int tHigh;
      void *data;
}

int main()
{
    struct packet pack;
    struct packet *pck;

    pack.len=3;
    pack.field=34;
    pack.tLow=712;
    pack.tHigh = 12903;
    pack.data = "message";

    pck = &pack;
    int *timeLow = (int * )pck + 4; // i want to get tLow 
    printf("Time Low :%d\n",*time);

    char *msg = (char *)pck + 12 ;// want data 
    printf("Message :%s\n",msg);

    return 0;
}
4

6 に答える 6

3

あなたは間違いなく標準的な方法を使用する方が良いでしょう

int *timeLow = &(pck->tLow);

コンパイラは、構造体の任意のメンバー間にパディング バイトを挿入できます。これらのパディング バイトのルールは、せいぜい実装で定義されているため、実装マニュアルを参照して、特定のケースでどのように (または場合に)、何バイト挿入されるかを確認する必要があります。また、パディング バイトの数は、さまざまなオプションを使用してコンパイルごとに、またはコンパイラごとに (コンピューターからコンピューターへ、...) 変更される可能性があることに注意してください。

Cマクロを使用してみることができますがoffsetof、きれいではありません:

size_t offset = offsetof(struct packet, tLow);
/* make sure offset is a multiple of sizeof (int*) */
int *timeLow = (int*)pck + offset / sizeof (int*);

(char*) または、キャストを使用して他の回答からコードをコピーすることで、少し醜くなります:-)

size_t offset = offsetof(struct packet, tLow);
int *timeLow = (int*)((char*)pck + offset);

おー!ソースにセミコロンがありません

于 2010-10-07T14:01:22.513 に答える
2

offsetofを探しています。

コードは次のようになります。

int *timeLow = (int*) ((char*)pck + offsetof(struct packet, tLow);

そしてpmgが指摘したように、

int *timeLow = &(pck->tLow);

構造体のメンバーへのポインターを取得する正規の方法です。

この回答は、テーブルにポインター演算ももたらしました-今日、pmgのおかげで学びました。

于 2010-10-07T13:56:59.640 に答える
2

基本的に、未定義の動作に依存しています。構造体のアライメントなど。とにかく...

(int*)pck + 4. ポインターを 4 * sizeof(int) 進めます。これは間違っています。構造体がパックされ、sizeof(short) == 2 であると仮定すると、1 だけ進めたいので...

int *timeLow = (int * )pck + 1; // i want to get tLow 
printf("Time Low :%d\n",*timeLow);

正しい結果を出力します。

メッセージに関しては、いくつかの汚いことをする必要があります。私は x86_64 を使用しているため、コンパイラは void* を 8 バイト境界でパディングすることを選択したため、オフセットは予想される 12 ではなく 16 でした。

基本的に、void* へのポインターをフェッチしています。したがって、コードは次のようになります。

char **msg = (char**)((char *)pck + 16) ;// want data 
printf("Message :%s\n",*msg);

このようなコードは絶対に書かないでください。これは要点を示しているだけです。

于 2010-10-07T13:57:37.233 に答える
1

あなたが書くとき

int *timeLow = (int * )pck + 4

「pck」を int ポインターとして扱っていますが、システムによっては 4 バイトまたは 8 バイトになる場合があります。4 intのオフセットを持つように指示しているため、構造体に正しくオフセットされません

代わりに、このようにする必要があります

int *timeLow = (int*)((short * )pck + 2); 
于 2010-10-07T13:50:17.347 に答える
0

short の長さは必ずしも 2 バイトではありません。指定されているのは、int のサイズ以下であるということだけです。おそらく sizeof() を使用する必要があります

于 2010-10-07T13:51:00.647 に答える
0

これは間違っています:pack.data = "message"; 未割り当てのメモリを使用しています。

また、これint *timeLow = (int * )pck + 4; は動作することが保証されていません (構造体のアライメントはコンパイラとシステムによって異なります)。

于 2010-10-07T13:51:41.290 に答える