我试图将其表达为谷歌,但未能找到任何有用的描述它。这是代码:
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
};
有人可以解释在没有数组或指针的情况下使用括号的含义吗?
答案 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)在处理字符数组时是相同的。