2012-02-11 11 views
9

私はこれをgoogleに明確にしようとしましたが、それを説明するのに役立つものが見つかりませんでした。コードは次のとおりです。奇妙なブラケットとマクロの構文が

struct Segdesc gdt[] = 
{ 
    // 0x0 - unused (always faults -- for trapping NULL far pointers) 
    SEG_NULL, 

    // 0x8 - kernel code segment 
    [GD_KT >> 3] = SEG(STA_X | STA_R, 0x0, 0xffffffff, 0), 

    // 0x10 - kernel data segment 
    [GD_KD >> 3] = SEG(STA_W, 0x0, 0xffffffff, 0), 

    // 0x18 - user code segment 
    [GD_UT >> 3] = SEG(STA_X | STA_R, 0x0, 0xffffffff, 3), 

    // 0x20 - user data segment 
    [GD_UD >> 3] = SEG(STA_W, 0x0, 0xffffffff, 3), 

    // 0x28 - tss, initialized in trap_init_percpu() 
    [GD_TSS0 >> 3] = SEG_NULL 
}; 

括弧の前に配列やポインタがない括弧の意味を説明できますか?

答えて

5

このあいまいな構文は、指定された初期化子と呼ばれ、配列集約を作成するときに要素をスキップできます。

は、このプログラムを見てみましょう:

#include <stdio.h> 
int a[] = { 
    1, [2]=3, [5]=7 
}; 
int main() { 
    int i; 
    for(i=0;i!=sizeof(a)/sizeof(int);i++) 
     printf("a[%d] = %d\n", i, a[i]); 
    return 0; 
} 

それは要素1、3、および配列aの4をスキップするように同じ構文を使用しています。

これは何、このプログラムがプリントされています

a[0] = 1 
a[1] = 0 
a[2] = 3 
a[3] = 0 
a[4] = 0 
a[5] = 7 

あなたのプログラムは、同じことを行いますが、それは構造体の配列を初期化し、コンパイル時定数のビットシフトを使用して、その配列の集計にインデックスを計算します。これらのインデックスの値は、コメント(0x08,0x10,0x18,0x20、および0x28)にあります。

+0

指定された初期化子は、C99の最も有用な新機能の1つです。 –

0

[]と*演算子は、定義するときに同じものに変換できます。ただし、スペースを割り当てるときには構文が異なります。

たとえば、a [1]と*(a + 1)は、文字の配列を扱うときは同じです。

+0

しかし、それは決して質問に答えるものではありません。 – Dan

+0

他の回答を見ても、今でも「これで質問に答えます」と思っていますか? –

6

これはdesignated initializerと呼ばれます。これはC99の機能です。ほとんどの場合、特定のインデックスの値を持つ配列を定義するときに便利です。 GCCページオフ

カンニング例は:

struct point p = { .y = yvalue, .x = xvalue }; 

int a[6] = { [4] = 29, [2] = 15 }; 

int a[6] = { 0, 0, 15, 0, 29, 0 }; 

に相当する "指定イニシャライザ" はまた、類似の方法で構造体を初期化する能力を指します

1

私はこの構文がC99で導入されたと考えていますが、私は決定的なものは何も見つかりません。いずれにしても、古いC言語の方言では、配列の3番目の要素など、明示的に初期化したい場合は、前の要素のゼロを明示的に指定する必要がありました。すなわち、

近代的なCで
int foo[4] = { 0, 0, 0, 42 }; // the 42 is arbitrary 

、あなたの代わりにこれを入力することができます。

int foo[4] = { [3] = 42 }; 

を構文は一種の曖昧ですが、直感は、私が思うに、何をやっていることはおおよそであるということです時間相当コンパイル:非常に大まかに

int foo[4]; 
foo[3] = 42; 

を、再度、コード例は

struct Segdesc gdt[(GD_TSS0 >> 3) + 1]; 
gdt[0] = SEG_NULL; 
gdt[GD_KT >> 3] = ...; 
... 
gdt[GD_TSS0 >> 3 ] = ...; 
と等価です

このシンタックスの利点は、配列の要素を数えずに正しい点に設定する配列を取得することなく、配列をより簡潔に初期化できることです。また、この構文は静的配列の初期化にも適用できます。