【问题标题】:weird bracket & macro syntax in cc中奇怪的括号和宏语法
【发布时间】:2012-02-11 05:27:03
【问题描述】:

我试图将这一点表达到谷歌中,但未能找到任何有用的描述它。代码如下:

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

谁能解释前面没有数组或指针的括号的含义??

【问题讨论】:

    标签: c arrays pointers macros


    【解决方案1】:

    这称为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 };
    

    【讨论】:

      【解决方案2】:

      这种晦涩的语法称为指定初始化器,它允许您在创建数组聚合时跳过元素。

      看看这个程序:

      #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
      

      您的程序做同样的事情,但它初始化一个结构数组,并使用编译时常量的位移位计算索引到它的数组聚合中。您可以在 cmets(0x08、0x10、0x18、0x20 和 0x28)中找到这些索引的值。

      【讨论】:

      • 指定初始化器是 C99 最有用的新特性之一。
      【解决方案3】:

      我认为这种语法是在 C99 中引入的,尽管在一个简短的谷歌调查中,我找不到任何确定的东西。无论如何,在较旧的 C 方言中,如果您想显式初始化,例如,数组的第三个元素,您必须显式列出前面元素的零。即,

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

      这种语法的优点是您可以更简洁地对数组进行稀疏初始化,而无需计算数组元素来获取要设置到正确位置的元素。此外,此语法可以应用于静态数组初始化。

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

        • 好的,但这绝不会回答问题。
        • 查看其他答案后,您是否仍然认为这“以现在的方式回答了问题”?
        猜你喜欢
        • 1970-01-01
        • 2016-08-26
        • 1970-01-01
        • 2010-11-24
        • 2011-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-06
        相关资源
        最近更新 更多