странные скобки и синтаксис макросов в c - PullRequest
9 голосов
/ 11 февраля 2012

Я пытался сформулировать это в 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
};

Может кто-нибудь объяснить смысл наличия скобок без массива или указателя перед ними ??

Ответы [ 4 ]

6 голосов
/ 11 февраля 2012

Это называется назначенным инициализатором .Это особенность 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 };
5 голосов
/ 11 февраля 2012

Этот скрытый синтаксис называется назначенным инициализатором, и он позволяет пропускать элементы при создании агрегата массива.

Посмотрите на эту программу:

#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 и 4 массива a.

Вот что печатает эта программа:

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

Ваша программа делает то же самое, но инициализирует массив структур и вычисляет индексы в агрегат массива, используя сдвиги битов констант времени компиляции. Вы можете найти значения этих индексов в комментариях (0x08, 0x10, 0x18, 0x20 и 0x28).

1 голос
/ 11 февраля 2012

Я думаю, что этот синтаксис был введен в C99, хотя в кратком обзоре Google я не могу найти ничего определенного.В любом случае, в старых диалектах Си, если вы хотите явно инициализировать, например, 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 ] = ...;

Преимущество этого синтаксиса в том, что вы можете сделать его более краткимредко инициализировать массив, без необходимости считать элементы массива, чтобы получить те, которые вы хотите установить в правильных местах.Кроме того, этот синтаксис может быть применен к инициализации статического массива.

0 голосов
/ 11 февраля 2012

В C оператор [] и * может определять одно и то же при определении.но при выделении пространства у них другой синтаксис.

например: a [1] и * (a + 1) идентичны при работе с массивом символов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...