奇怪的支架& c中的宏语法

时间:2012-02-11 05:27:04

标签: c arrays pointers macros

我试图将其表达为谷歌,但未能找到任何有用的描述它。这是代码:

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
};

有人可以解释在没有数组或指针的情况下使用括号的含义吗?

4 个答案:

答案 0 :(得分:6)

这称为designated initializer。这是一个C99功能。在定义大多数为零的数组时,它非常有用,在特定索引处有一些值。

GCC页面上的示例:

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

相当于

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

“指定初始化程序”也指以类似方式初始化结构的能力:

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

答案 1 :(得分: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;
}

它使用相同的语法跳过数组a的元素1,3和4.

这是该程序打印的内容:

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

您的程序执行相同的操作,但它初始化一组结构,并使用编译时常量的位移计算索引到其数组聚合中。您可以在注释中找到这些索引的值(0x08,0x10,0x18,0x20和0x28)。

答案 2 :(得分:1)

我认为这种语法是在C99中引入的,虽然在简短的谷歌调查中,我找不到任何确定的东西。在任何情况下,在较旧的C语言中,如果要显式初始化(​​例如,数组的第3个元素),则必须为前面的元素显式列出零。即,

int foo[4] = { 0, 0, 0, 42 };    // the 42 is arbitrary

在现代C中,您可以输入:

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 ] = ...;

这种语法的优点是你可以更简洁地稀疏地初始化一个数组,而不必计算数组元素来获得你想要设置到正确位置的数组。此外,此语法可应用于静态数组初始化。

答案 3 :(得分:0)

在C中,[]和*运算符在定义时可以转换为相同的东西。但是,在分配空间时,它们具有不同的语法。

例如:a [1]和*(a + 1)在处理字符数组时是相同的。