如何在C中初始化for(;;)循环中的多个变量?

时间:2021-04-21 22:34:47

I thought one could initialize several variables in a for loop:

我认为可以在for循环中初始化几个变量:

for (int i = 0, char* ptr = bam; i < 10; i++) { ... }

But I just found out that this is not possible, gcc gives the following error:

但我刚发现这是不可能的,gcc给出了以下错误:

error: expected unqualified-id before 'char'

Is it really true that you can't initialize variables of different types in a for loop?

你真的不能在for循环中初始化不同类型的变量吗?

6 个解决方案

#1


41  

You can (but generally shouldn't) use a local struct type.

您可以(但通常不应该)使用本地结构类型。

for ( struct { int i; char* ptr; } loopy = { 0, bam };
      loopy.i < 10 && * loopy.ptr != 0;
      ++ loopy.i, ++ loopy.ptr )
    { ... }

Since C++11, you can initialize the individual parts more elegantly, as long as they don't depend on a local variable:

由于c++ 11,您可以更优雅地初始化各个部分,只要它们不依赖于局部变量:

for ( struct { int i = 0; std::string status; } loop;
      loop.status != "done"; ++ loop.i )
    { ... }

This is just almost readable enough to really use.

这是几乎可读的足以真正使用。


C++17 is scheduled to address the problem with structured bindings:

c++ 17计划解决结构化绑定的问题:

for ( auto [ i, status ] = { 0, ""s }; status != "done"; ++ i )

However, the detailed feature set and syntax are still in flux.

然而,详细的特性集和语法仍在变化中。

#2


13  

It's true that you can't simultaneously declare and initialize declarators of different types. But this isn't specific to for loops. You'll get an error if you do:

的确,您不能同时声明和初始化不同类型的声明符。但这并不是for循环特有的。如果你这样做,你会得到一个错误:

int i = 0, char *ptr = bam;

too. The first clause of a for loop can be (C99 §6.8.5.3) "a declaration" or a "void expression". Note that you can do:

了。第一个for循环可以条款(C99§6.8.5.3)“声明”或“无效表达式”。注意,您可以:

int i = 0, *j = NULL;
for(int i = 0, *j = NULL;;){}

because i and *j are both of type int. The exact syntax for a declaration is given in §6.7

因为我和* j都是int类型的。声明的语法§6.7中给出

#3


12  

If you really need the variables to stay in the scope of the loop you could write

如果您真的需要变量保持在循环的范围内,您可以编写

{ char* ptr = bam; for (int i = 0; i < 10; i++) { ... } }

It's a bit ugly, but works.

它有点丑,但很管用。

#4


4  

try this:

试试这个:

int i;
char* ptr;
for (i = 0, ptr = bam; i < 10; i++) { ... }

#5


-1  

According to http://linuxsoftware.co.nz/cppgrammar.html#for-init-statement you can get only simple declaration or an expression (which is not permitted to contain declaration) in the for-init statement. That means the answer is no (if I analyzed the BNF correctly :) )

根据http://linuxsoftware.co.nz/cppgrammar。在for-init语句中,只能获得简单的声明或表达式(不允许包含声明)。这意味着答案是否定的(如果我正确地分析了BNF:)

#6


-3  

I think the languages they teach you kids these days are meant to handcuff you and rot your brain so you just be quiet and put the lego blocks together in the very limited form in which they are meant to snap together so you build mediocre stuff. The beauty of C is that you can follow the rules, and in a clever way, to get what you want. Here is how you write this loop with extra initialzers. Here is a working example that shows you how to bridge an extended loop onto a first. You use the first to pirate its variables and they remain in scope. You use a dummy variable to make the outer loop run once. A smart compiler will note the fact and nuke the loop with the loop unroller. So for you it is just benefit. The second array then uses some variables from the first declaration and the second declaration and runs to completion. It is a trivial example just meant you to be able to understand how to do it without the heavy handed move of throwing in some scoping. Because this technique can be used with macros when written like this in order to create beautiful next-generation like structure enumeration, like "for value in array do", of which I have many.

我认为他们现在教给你们的语言是用来束缚你们,腐蚀你们的大脑,所以你们要安静,把乐高积木以非常有限的形式组合在一起,这样你们就可以构建平庸的东西。C的美妙之处在于,你可以遵循规则,用一种聪明的方式,得到你想要的。下面是如何使用额外的初始化器编写这个循环。这里有一个工作示例,向您展示如何将扩展循环连接到第一个循环。您使用第一个海盗它的变量,它们仍然在作用域中。使用虚拟变量使外部循环运行一次。一个聪明的编译器会注意到这个事实,用循环解滚的方法来处理循环。所以对你来说,这只是好处。然后第二个数组使用第一个声明和第二个声明中的一些变量,并运行到完成。这是一个微不足道的示例,它只是意味着您能够理解如何在不需要费力地抛出某个范围的情况下完成它。因为这种技术可以在编写时使用宏,以便创建漂亮的下一代结构枚举,比如“for value in array do”,其中我有很多。

#include "stdio.h"
int
main(int argc, char **argv)
{
    const int max=7;
    const char *array[7] = {
    "hello","you","kids","who","don't","know","malloc\n"
    };

    for(int i=0,count=max,$=1;$;$=0)
    for(const char **p=array;count<max;i++)
    {
        printf("%s ",p[i]);
    }
}

There is nothing missing here. This technique of for loop joining with a one shot for loop has been used to embed in a call to get an enumerator for this hash object, and start the enumeration, to get the values extracted for the key and value, and also by convenience create them as void pointers for the user, he just has to name them. Then they are filled, and the enumeration will continue until all keys and values are done. If the user breaks in the iteration the whole cascade of oneshot forloops will fall apart as we'd want because they're probably not even there since they were constructed with simple const ops that the compiler can see will unroll the loop. So basically it lets you extend the syntax to do things like this with no penalty.

这里没有遗漏什么。这种技术的for循环加入一枪for循环已经被用于嵌入在这个哈希对象调用一个枚举器,并开始枚举,值的键和值的提取,并通过方便为用户创建他们为空指针,他只需要说出他们。然后填充它们,枚举将继续,直到完成所有键和值。如果用户在迭代中中断,就会像我们想要的那样崩溃,因为它们可能根本就不在那里,因为它们是用简单的const操作系统构建的,编译器可以看到它会打开循环。基本上,它允许你扩展语法来做这样的事情而不受惩罚。

But you need to know a bit of C and at least have your head out of the robot box that the schools are putting them in these days with these toy languages.

但是你需要知道一些C语言,至少你可以从机器人的盒子里拿出你的头,这些日子里学校用这些玩具语言。

#1


41  

You can (but generally shouldn't) use a local struct type.

您可以(但通常不应该)使用本地结构类型。

for ( struct { int i; char* ptr; } loopy = { 0, bam };
      loopy.i < 10 && * loopy.ptr != 0;
      ++ loopy.i, ++ loopy.ptr )
    { ... }

Since C++11, you can initialize the individual parts more elegantly, as long as they don't depend on a local variable:

由于c++ 11,您可以更优雅地初始化各个部分,只要它们不依赖于局部变量:

for ( struct { int i = 0; std::string status; } loop;
      loop.status != "done"; ++ loop.i )
    { ... }

This is just almost readable enough to really use.

这是几乎可读的足以真正使用。


C++17 is scheduled to address the problem with structured bindings:

c++ 17计划解决结构化绑定的问题:

for ( auto [ i, status ] = { 0, ""s }; status != "done"; ++ i )

However, the detailed feature set and syntax are still in flux.

然而,详细的特性集和语法仍在变化中。

#2


13  

It's true that you can't simultaneously declare and initialize declarators of different types. But this isn't specific to for loops. You'll get an error if you do:

的确,您不能同时声明和初始化不同类型的声明符。但这并不是for循环特有的。如果你这样做,你会得到一个错误:

int i = 0, char *ptr = bam;

too. The first clause of a for loop can be (C99 §6.8.5.3) "a declaration" or a "void expression". Note that you can do:

了。第一个for循环可以条款(C99§6.8.5.3)“声明”或“无效表达式”。注意,您可以:

int i = 0, *j = NULL;
for(int i = 0, *j = NULL;;){}

because i and *j are both of type int. The exact syntax for a declaration is given in §6.7

因为我和* j都是int类型的。声明的语法§6.7中给出

#3


12  

If you really need the variables to stay in the scope of the loop you could write

如果您真的需要变量保持在循环的范围内,您可以编写

{ char* ptr = bam; for (int i = 0; i < 10; i++) { ... } }

It's a bit ugly, but works.

它有点丑,但很管用。

#4


4  

try this:

试试这个:

int i;
char* ptr;
for (i = 0, ptr = bam; i < 10; i++) { ... }

#5


-1  

According to http://linuxsoftware.co.nz/cppgrammar.html#for-init-statement you can get only simple declaration or an expression (which is not permitted to contain declaration) in the for-init statement. That means the answer is no (if I analyzed the BNF correctly :) )

根据http://linuxsoftware.co.nz/cppgrammar。在for-init语句中,只能获得简单的声明或表达式(不允许包含声明)。这意味着答案是否定的(如果我正确地分析了BNF:)

#6


-3  

I think the languages they teach you kids these days are meant to handcuff you and rot your brain so you just be quiet and put the lego blocks together in the very limited form in which they are meant to snap together so you build mediocre stuff. The beauty of C is that you can follow the rules, and in a clever way, to get what you want. Here is how you write this loop with extra initialzers. Here is a working example that shows you how to bridge an extended loop onto a first. You use the first to pirate its variables and they remain in scope. You use a dummy variable to make the outer loop run once. A smart compiler will note the fact and nuke the loop with the loop unroller. So for you it is just benefit. The second array then uses some variables from the first declaration and the second declaration and runs to completion. It is a trivial example just meant you to be able to understand how to do it without the heavy handed move of throwing in some scoping. Because this technique can be used with macros when written like this in order to create beautiful next-generation like structure enumeration, like "for value in array do", of which I have many.

我认为他们现在教给你们的语言是用来束缚你们,腐蚀你们的大脑,所以你们要安静,把乐高积木以非常有限的形式组合在一起,这样你们就可以构建平庸的东西。C的美妙之处在于,你可以遵循规则,用一种聪明的方式,得到你想要的。下面是如何使用额外的初始化器编写这个循环。这里有一个工作示例,向您展示如何将扩展循环连接到第一个循环。您使用第一个海盗它的变量,它们仍然在作用域中。使用虚拟变量使外部循环运行一次。一个聪明的编译器会注意到这个事实,用循环解滚的方法来处理循环。所以对你来说,这只是好处。然后第二个数组使用第一个声明和第二个声明中的一些变量,并运行到完成。这是一个微不足道的示例,它只是意味着您能够理解如何在不需要费力地抛出某个范围的情况下完成它。因为这种技术可以在编写时使用宏,以便创建漂亮的下一代结构枚举,比如“for value in array do”,其中我有很多。

#include "stdio.h"
int
main(int argc, char **argv)
{
    const int max=7;
    const char *array[7] = {
    "hello","you","kids","who","don't","know","malloc\n"
    };

    for(int i=0,count=max,$=1;$;$=0)
    for(const char **p=array;count<max;i++)
    {
        printf("%s ",p[i]);
    }
}

There is nothing missing here. This technique of for loop joining with a one shot for loop has been used to embed in a call to get an enumerator for this hash object, and start the enumeration, to get the values extracted for the key and value, and also by convenience create them as void pointers for the user, he just has to name them. Then they are filled, and the enumeration will continue until all keys and values are done. If the user breaks in the iteration the whole cascade of oneshot forloops will fall apart as we'd want because they're probably not even there since they were constructed with simple const ops that the compiler can see will unroll the loop. So basically it lets you extend the syntax to do things like this with no penalty.

这里没有遗漏什么。这种技术的for循环加入一枪for循环已经被用于嵌入在这个哈希对象调用一个枚举器,并开始枚举,值的键和值的提取,并通过方便为用户创建他们为空指针,他只需要说出他们。然后填充它们,枚举将继续,直到完成所有键和值。如果用户在迭代中中断,就会像我们想要的那样崩溃,因为它们可能根本就不在那里,因为它们是用简单的const操作系统构建的,编译器可以看到它会打开循环。基本上,它允许你扩展语法来做这样的事情而不受惩罚。

But you need to know a bit of C and at least have your head out of the robot box that the schools are putting them in these days with these toy languages.

但是你需要知道一些C语言,至少你可以从机器人的盒子里拿出你的头,这些日子里学校用这些玩具语言。