2016-09-14 1 views
0

私たちには、構造ヘッダが最初のメンバとして存在する多くの異なる構造のデータがあるとします。ヘッダーと異なるブロブが、任意のサイズのものであるとします。 それからtrueまたはfalseは、構造体のいずれかへのポインタを反復すると仮定します構造体ヘッダポインタはその構造体の次のメンバのアドレスになりますか?このようなシナリオでは、Cデータの配置要件はどのようになっていますか?Cの次のデータブロブへのポインタを反復することは安全ですか?

編集:例えば、少なくとも私のシステムでは、ターゲットのポインタがオフセットされていることを示す作業コードでas suggested by Olafが更新されています。私の主な質問に対する答えが「偽」であることを意味しています。とにかく関連する回答ありがとう!もし(メモリアライメントの理由から、例えば、)のメンバー間にパディングが存在し得るようstruct部材のアドレスをインクリメントすることは、次のメンバのアドレスを与えると仮定することができない一般的なケースで

#include <stdio.h> 

struct Header { 
    char data_b; 
}; 

struct Data { 
    struct Header header; 
    int data; 
}; 

void *Header_skip(void *big_or_small) { 
    return (struct Header *)big_or_small + 1; 
} 

int main(int argc, char const *argv[]) { 
    struct Data x = { .data = 2 }; 
    int *data = (int *)Header_skip(&x); 

    printf("Expected: %p\n", &x.data); 
    printf("Actual: %p\n", data); 
    printf("Offset: %lld\n", (long long)data - (long long)&x.data); 

    return 0; 
} 
+1

いいえ、 'Header'フィールドは埋め込まれている可能性があるので、' any_struct + 1'はこのパディングの先頭を指します。 –

+0

あなたが達成しようとしていることは明確ではありません。 [ask]を見て、[mcve]を提供してください。パディングなどを分けて、返されたポインタを 'Header' **や**型のヘッダ以外のものとして逆参照すると、そのアドレスに' Header'があると未定義の振る舞いを引き起こします。 – Olaf

+0

@Olaf質問を更新しました、リンクありがとうございます! – skogshjort

答えて

1

これらの構造体のいずれかへのポインタを構造体のヘッダーポインタとして反復すると、その構造体の次のメンバーのアドレスが返されると仮定するとtrueかfalseですか?

このような前提をするのは安全ではありません。 Cの実装では、任意の構造体型と一致するように、構造体メンバ間に任意の量のパディングを置くことができます。したがって、大まかに言って、あなたの関数は、ヘッダに続くメンバへのポインタではなく、パディングへのポインタを生成する可能性があります。

このようなシナリオでは、Cデータの配置要件はどのようになっていますか?いずれの場合(例えば、鋳造時に悪いのポインタへの最終的なスロップリードをできますか?)

Cの実装では、一般的にメンバー間で挿入するために、どのくらいのパディングを決定する際に、アライメントの要件を使用しますが、標準ではそうするためにそれらを必要としません。一般に、実装がどのようにその決定を下すのかを制約しません。

3

offsetofを使用して、目的のメンバの正確なオフセットを決定することができます。

+0

OPは知られているメンバーではなく、既知のメンバーの次のメンバーを取得したいので、 'offsetof'はここでは役に立たないと思います。 –

+0

そのオフセットを渡し、ポインタを 'char *'として扱う必要があります。 – Olaf

+0

@EugeneSh。以下のメンバにアクセスするには、その型も知られていなければなりません(または、アドレスが正しい型のポインタにキャストできないので役に立たないでしょう)ので、 'offsetof'を' struct ' 「ヘッダー」とそれに続くメンバーにアクセスします。 – Arkku

関連する問題