2016-03-21 8 views
0

構造体へのポインタが渡されていますが、最初の8つのメンバーは同じサイズですが、インデックスでアクセスできますか?インデックスによる構造体へのアクセス

typedef struct example{ 
    uint64_t one; 
    uint64_t two; 
    uint64_t three; 
    uint64_t four; 
    uint64_t five; 
    //etc... 

    uint8_t ninth; 

} example_t; 


void example_method(example_t *ptr) 
{ 
    //can I do this? 
    &ptr[2] // which would be equal to the uint64_t third? 
} 
+1

詐欺的であり、動作が保証されていない不正行為が必要です。おそらく配列のみを使用するか、おそらく配列とその下部構造の「共用体」を使用して構造体を再設計する方が良いでしょう(それについてのいくつかの注意点もあります)。使用パターンに合わせて構造を設計するのが最善です。配列として扱う必要がある場合は、配列として格納します。 –

+0

@ JonathanLefflerと合意すれば、構造を再設計する方がよいでしょう。 – blazs

答えて

0

いいえ、できません。 ptr[2]と記載すると*(ptr+2)に相当し、最初にアドレスptrsizeof(struct example)を追加し、逆参照します。

struct example { 
    uint64_t members[8]; 
    uint8_t ninth; 
}; 

その場合、あなたはptr->members[2]で配列の3番目の要素にアクセスすることができます。

はもちろん、あなたの代わりに8人のメンバーの構造体の配列を持つことができます。メンバーの名前がなどonetwo、されていない場合、あなたは

enum Member_Names { 
    FIRST_NAME = 0, 
    SECOND_NAME = 1, 
    ..., 
    EIGTH_NAME = 7 
}; 

を定義し、その後ptr->members[THIRD_NAME]を使用することができます。

+0

メンバーのインデックスで構造体にアクセスする方法はありませんか? – Anon

+0

いいえ、私はそこにいるとは思わない。もちろん、9つのメンバの代わりに構造体に配列を持つことができます: 'struct example {uint64_t members [8]; uint8_t 9; } 'この場合、' ptr-> members [2] 'で配列の2番目の要素にアクセスできます。 – blazs

+0

私は3番目の要素を意味し、2番目の要素は意味しません。ごめんなさい。 :) – blazs

2

構造体メンバをインデックスで確実に取得できない理由は、構造体にメンバ間および最後のメンバの後に任意の埋め込みが含まれている可能性があるためです。 C11によると、N1570§6.7.2.1/ P15 構造体と共用体指定子

ではなく、その 初めに、構造物内の無名のパディングがあるかもしれません。

あなたができることは、構造体を配列メンバー(または可能であればflexible array member)に再定義することです。

+0

妥当な答え---フレキシブルなアレイメンバーを認識していませんでした。 :)パディングがない場合でも、どのようにインデックスを使用して構造体メンバーにアクセスしますか? – blazs

+0

@blazs:AFAIRは、このようにメンバーにアクセスする唯一の標準準拠の機能で、 'offsetof'マクロを使用することです。その理由の1つはパディングであり、2つ目は、タイプが異なるサイズ(およびアライメント要件)である可能性があるということです。 –

+0

@blazs:Grezegorzは次のように書いています。配列メンバーを使用してください。ハッキーなことについても考えません。要素の名前はすでに数値索引付けを暗示しています。 – Olaf

0

あなたは違っを構築場合、コードは今、あなたはできませんが、あなたが離れて得ることができるとの見え方は、次のとおりです。

typedef union example 
{ 
    struct { 
      uint64_t one; 
      uint64_t two; 
      uint64_t three; 
      uint64_t four; 
      uint64_t five; 
      //etc... 

      uint8_t ninth; 

    }; 
    uint64_t array[9]; 
}example_t; 

を今すぐあなたが行うことができます:

void example_method(example_t *ptr) 
{   
    ptr->array[2]; // access fields by index 
} 

しかし、コンパイラのアラインメントのデフォルトのために問題に陥る可能性があります。たとえば、の文字列のフィールドを1つ追加したとすると、コンパイラは4バイトに合わせようとするかもしれません。物事を混乱させ、特にフィールドは、あなたの構造体の真ん中のどこかにあります。

+1

'ptr-> array [2]'を実行すると、メンバー 'three'にアクセスしていることに注意してください。 –

+1

@JonathanLefflerあなたが運が良ければ、パディングはありません。あなたが持っている唯一の確実性は 'ptr [0]'と 'ptr-> one'は同じです –

+0

@EliasVanOotegem:構造体の先頭に同じ型のN要素のシーケンスがある場合は、コンパイラは、要素間にパディングを追加します(ビットフィールドではないと仮定します)。異なるタイプがある場合、特に厳密なアライメントを必要とするタイプが、構造内のストリンジェントなアライメントを必要としないタイプに続く場合には、パディングが現れる。 '第9の要素(' int64_t'ではなく 'int8_t')はおそらく前にパディングがありません。それはおそらくそれの後にパディングを持つでしょう。しかし、はい、それはコンパイラがあなたをいじめる可能性があります。この場合、通常はそうではありません。 –

関連する問題