在for循环中声明匿名结构,clang无法编译 [英] Declaring anonymous struct in for loop, clang fails to compile
问题描述
在for循环中声明匿名结构的代码在带有-std = c99 / gnu99的gcc中可以正常工作
Code declaring anonymous structs in a for loop worked fine in gcc with -std=c99/gnu99
for (struct {int foo; int bar;} i = {0}; i.foo < 10; i.foo++);
但是当我改用clang时,却出现错误:
However when I switch to clang instead I got the error:
error: declaration of non-local variable in 'for' loop
为什么会出错?为什么要允许某些类型(例如 int)而不允许其他类型(例如struct {int foo;})?这似乎不一致。 clang是否无法正确实现c99还是代码无效的c99和gcc恰好支持c99?
Why is this an error? Why would it allow some types (e.g. "int") but not others (e.g. struct {int foo;}) ? This seems inconsistent. Does clang fail to implement c99 correctly or is that code invalid c99 and gcc just happens to support it?
有人知道一种声明多种类型变量的方法吗?在clang支持的for循环中? (这对宏很有用。)
Does anyone know of a way to declare more than one type of variable in a for loop that is supported by clang? (This is useful for macros.)
编辑:
由于人们问为什么这有用,所以我将粘贴一些示例代码:
Since people asked why this is useful I will paste some example code:
#define TREE_EACH(head, node, field, iterator) for ( \
/* initialize */ \
struct { \
node* cur; \
node* stack[((head)->th_root == 0? 0: (head)->th_root->field.avl_height) + 1]; \
uint32_t stack_size; \
} iterator = {.cur = (head)->th_root, .stack_size = 0}; \
/* while */ \
iterator.cur != 0; \
/* iterate */ \
(iterator.stack_size += (iterator.cur->field.avl_right != 0) \
? (iterator.stack[iterator.stack_size] = avl_right, 1) \
: 0), \
(iterator.cur = (iterator.cur->field.avl_left == 0) \
? iterator.cur->field.avl_left \
: (iterator.stack_size > 0? (iterator.stack_size--, iterator.stack[iterator.stack_size]): 0)) \
)
这是我写的一个非常方便的宏,它按深度优先顺序遍历AVL树堆栈。由于不允许在for循环中声明匿名结构,尽管我不得不使宏使用起来不那么直观。我无法将声明外包到树的其余部分,因为它使用了可变长度的数组。
This is a really convenient macro that I wrote which iterates over an AVL tree in depth-first order on the stack. Since declaring anonymous structs in the for loop is not allowed though I have to make the macro less intuitive to use. I could not possible out-source the declaration to the rest of the tree since it uses a variable length array.
推荐答案
我对先前的答案深信不疑。它可以使用gcc(带有 -Wall -pedantic
)成功构建,而不能仅使用clang或Visual Studio。
I'm respectfully unconvinced by the previous answers. It builds successfully with gcc (with -Wall -pedantic
), only not with clang nor Visual Studio.
Microsoft在此 Microsoft Connect错误项。
Microsoft have acknowledged as a bug an extremely similar issue with Visual Studio at this Microsoft Connect bug item.
6.8.5表示 for-init-expression 中的标识符声明不能为 typedef
, extern
或 static
(除 auto <之外的唯一存储类说明符) / code>和
注册
)。
6.8.5 is saying that declarations of identifiers inside the for-init-expression cannot be typedef
, extern
or static
(the only storage class specifiers other than auto
and register
).
C99中的存储类说明符 auto
是默认值,是隐式的。然后,结构类型和标识符 i
是自动的(在该代码块中具有作用域)。代码肯定有效吗?我看不到6.8.5如何禁止类型的声明。
The storage class specifier auto
in C99 is default and is implicit. The struct type and identifier i
are then auto (have scope within that code block). Surely the code is then valid? I don't see how 6.8.5 is forbidding the declaration of a type.
我建议gcc是正确的,这是clang和Visual Studio实施的错误。
I suggest that gcc is correct, and it's a bug with the implementation by clang and Visual Studio.
这篇关于在for循环中声明匿名结构,clang无法编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!