【问题标题】:Range Initialization of a C ArrayC 数组的范围初始化
【发布时间】:2011-10-18 07:32:06
【问题描述】:

非常简单的问题,在哪里这段代码在哪里工作?

static void *gostruct[] = 
{
    [0 ... 255] = &&l_bad,
    ['\t'] = &&l_loop, [' '] = &&l_loop, ['\r'] = &&l_loop, ['\n'] = &&l_loop,
    ['"'] = &&l_qup,
    [':'] = &&l_loop,[','] = &&l_loop,
    ['['] = &&l_up, [']'] = &&l_down, // tracking [] and {} individually would allow fuller validation but is really messy
    ['{'] = &&l_up, ['}'] = &&l_down,
    ['-'] = &&l_bare, [48 ... 57] = &&l_bare, // 0-9
    ['t'] = &&l_bare, ['f'] = &&l_bare, ['n'] = &&l_bare // true, false, null
};

通读它可以清楚地看到它将包含 256 个条目的数组初始化为值 &&l_bad,然后用特定值覆盖某些索引。但是这段代码不能在我可以访问的 VS2010 中编译,所以我想知道这是有效的 C 代码。

注意:这段代码 sn-p 取自 JSON parser on github,据我了解,它创建了用于处理 JSON 字符串的跳转表。

【问题讨论】:

  • 我相信这是使用 gcc 扩展。

标签: c arrays initialization


【解决方案1】:

此构造称为 Designated Initializers
在指定初始化器中使用 Range 是 GNU gcc 特定的扩展。

要将一系列元素初始化为相同的值,请编写 [first ... last] = value .这是一个 GNU 扩展。例如,

int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };

-pedantic 编译会告诉你。
请注意,它是不可移植的,因为它是编译器特定的扩展。

【讨论】:

  • 指定初始化器不是 gcc 扩展(除了 gcc 在 C89 模式下允许它们),但在指定初始化器中使用 ... 是。
  • 谢谢,在大多数搜索引擎中搜索这种语法似乎相当困难,因此非常感谢它的名称。
【解决方案2】:

这是使用数字 GNU C 扩展。

http://www.gnu.org/s/gnu-c-manual/gnu-c-manual.html

'as a GNU C extension, you can initialize a range of elements 
to the same value, by specifying the first and last indices, in the 
form [first] ... [last]'

'As a GNU C extension, you can also take the address of a label 
with the label address operator &&. The result is a void* pointer 
which can be used with goto.'

看起来这很可能被用作解析器的跳转表, 如果您打算将其移植到 Windows,则需要重写整个部分。

您可能会发现您将实现一个简单的 switch 语句并替换 查找和跳转,像 perl 这样的东西会帮助你“打字” 练习:)

【讨论】:

  • && 害死我了!谢谢!
【解决方案3】:

根据参考

在 ISO C99 中,您可以按任何顺序指定元素,指定它们适用的数组索引或结构字段名称,GNU C 也允许将其作为 C90 模式的扩展。此扩展未在 GNU C++ 中实现。

范围和特定初始化程序均受 ISO C99 支持,并且不仅是 GNU 扩展。您可以尝试在 Visual Studio 2010 中启用 ISO C99(我不知道如何)。

参考:https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html

【讨论】:

  • 除上述信息外,这可能对其他人有所帮助。 Microsoft 在其 C++ 环境中对 C 标准的支持大部分时间都是按需提供的。如果标准/功能的需求量不大,那么通常是。由于始终避免 goto 的观点(而不是理解每个逻辑或 func 调用都是 goto),因此 Visual Studio 不太可能支持此功能。 (但是我最近没有检查过)
【解决方案4】:

在指定的初始化程序中使用范围是 gcc 扩展,标准 C99 不支持。

代码还获取标签的地址,我相信这也是一个 gcc 扩展。

所以,这不是有效的 C 代码,只是有效的 gcc c 代码。

【讨论】:

    猜你喜欢
    • 2012-04-04
    • 1970-01-01
    • 2015-08-14
    • 1970-01-01
    • 2016-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多