構造体宣言の最後にあるこの[1]の目的は何ですか?


96

私はMSP430マイクロコントローラーのヘッダーファイルを調べていましたが、次の場所で遭遇しました<setjmp.h>

/* 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 */

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


5
ポインタへの腐敗と関係があるのでしょうか?
Elazar 2017年

3
最後のコメントはまったく間違っているようです...
R .. GitHub ICEのヘルプの停止

回答:


115

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

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


12
また、を介し=たコピーも防止されます。
melpomene 2017年

11
それはひどいです。最小時間が経過したら、この回答を受け入れます。ご協力いただきありがとうございます!
アレクサンダー-モニカを2017年

3
@Alexander:typedefこのような方法でカプセル化した場合、それほど粗くはありません。ええ、その場限りのことはちょっとひどいかもしれませんが、APIユーザーが参照と非参照のセマンティクス(それは常に参照渡しである必要がある)について考える必要がないかすかに不透明なタイプがある場合、それは合理的な方法です自動参照セマンティクスを他の方法では欠けている言語に追加する方法。ユーザーが型を受け取る独自のAPIを作成する場合でも機能します。Cでは、引数として配列を受け入れることを宣言すると、実際にはポインターを受け入れることになるためです。すべてが「うまくいく」。
ShadowRanger 2017年

4
@ShadowRangerそれは巧妙なトリックですが、それ... otherwise lacks itについての全体的なものです。回避策自体ではなく、Cの制限
アレクサンダー-モニカの復活2017年

34
IMOそれはひどいです。GMPを初めて使用したときは、数値が明らかに値で渡されているため、GMPがどのように機能するのか理解できませんでした。私はそれを困惑させるためにGMPヘッダーを掘り下げる必要がありました。それは、実際にCをすでに知っている人たちの前で飛ぶだけです。次に*、コードでを探すのではなく、どのパラメーターが値によって渡され、どのパラメーターが参照であるかを追跡する必要があります。
MM
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.