2017-11-02 3 views
86

私は私のMSP430マイクロコントローラのヘッダファイルを通じてスヌーピングた、と私は<setjmp.h>でこれに走った:構造体宣言の最後のこの[1]の目的は何ですか?

/* r3 does not have to be saved */ 
typedef struct 
{ 
    uint32_t __j_pc; /* return address */ 
    uint32_t __j_sp; /* r1 stack pointer */ 
    uint32_t __j_sr; /* r2 status register */ 
    uint32_t __j_r4; 
    uint32_t __j_r5; 
    uint32_t __j_r6; 
    uint32_t __j_r7; 
    uint32_t __j_r8; 
    uint32_t __j_r9; 
    uint32_t __j_r10; 
    uint32_t __j_r11; 
} jmp_buf[1]; /* size = 20 bytes */ 

私はそれがjmp_bufに匿名の構造体とのtypedefのそれを宣言することを理解し、私は何を把握することはできません[1]はのためです。私はjmp_bufが(この匿名の構造体の)1つのメンバを持つ配列であると宣言していることは知っていますが、どのようなものが使用されているのか想像できません。何か案は?

+5

ポインタに崩壊するとはどういうことでしょうか? – Elazar

+3

最終的なコメントはまったく間違っています... –

+0

優秀な質問! – SRG

答えて

103

これは、関数引数として使用すると、プログラマが明示的に&演算子を使用する必要なく、最初の要素へのポインタに単一要素配列を劣化させる、Cの「参照型」を作成する一般的なトリックです。その住所を取得する。宣言されているところでは、実際のスタック型(動的割り当ては不要)ですが、引数として渡されると、呼び出された関数はコピーではなくポインタを受け取り、安価に渡されますconst)。

GMPは同じタイプのトリックを使用します。その構造は動的に割り当てられたメモリへのポインタを管理するため、ここで重要です。 mpz_init関数は構造体へのポインタの取得に依存しており、構造体のコピーではなく、まったく初期化できませんでした。同様に、多くの操作は動的に割り当てられたメモリのサイズを変更することができ、呼び出し元の構造体を変更できない場合は動作しません。

+12

また、 '='を使ってコピーすることもできません。 – melpomene

+11

それは総体です。私は、最小時間が経過すると、この答えを受け入れます。ご協力いただきありがとうございます! – Alexander

+2

@Alexander:このような 'typedef'でカプセル化した場合、それほど重大ではありません。うん、このアドホックを行うのはちょっとひどいですが、APIユーザーがリファレンスと非リファレンスのセマンティクスについて考える必要がない(APIは常に*参照で渡す必要があります)、かすかに不透明なタイプの場合は、自動参照セマンティクスをそれ以外の言語に追加する合理的な方法です。 Cで、配列を引数として受け入れると宣言するのは実際にはポインタを受け入れることを意味するため、ユーザーが型を受け取る独自のAPIを書く場合にも機能します。すべてが "うまくいく"。 – ShadowRanger

関連する問題