C/C++:转到for循环

Ser*_*gey 12 c c++ compiler-construction goto

我有点不寻常的情况 - 我想使用goto语句跳转循环中,而不是跳出它.

有充分理由这样做 - 这段代码必须是某个函数的一部分,它在第一次调用后进行一些计算,返回请求新数据并需要再继续调用一次.函数指针(明显的解决方案)无法使用,因为我们需要与不支持函数指针的代码进行互操作.

我想知道下面的代码是否安全,即它将由所有符合标准的C/C++编译器正确编译(我们需要C和C++).

function foo(int not_a_first_call, int *data_to_request, ...other parameters... )
{
    if( not_a_first_call )
        goto request_handler;
    for(i=0; i<n; i++)
    {
        *data_to_request = i;
        return;
request_handler:
        ...process data...
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经研究过标准,但是关于这种用例的信息并不多.我也想知道是否更换等效,同时将但从便携性点有益的.

提前致谢.

UPD:感谢所有评论过的人!

  1. 对所有评论者:)是的,我明白我不能跳过局部变量的初始化器,我必须i在每次调用时保存/恢复.

  2. 关于强大的原因:)这段代码必须实现反向通信接口.反向通信是一种试图避免使用函数指针的编码模式.有时,它有它,因为预计你遗留代码中使用使用它.

不幸的是,r-comm-interface无法以很好的方式实现.您不能使用函数指针,也无法轻松地将工作拆分为多个函数.

Jos*_*e_X 10

似乎完全合法.

根据goto声明部分中的C99标准草案http://std.dkuug.dk/JTC1/SC22/WG14/www/docs/n843.htm:

[#3] EXAMPLE 1 It is sometimes convenient to jump  into  the
   middle  of  a  complicated set of statements.  The following
   outline presents one possible approach to a problem based on
   these three assumptions:

     1.  The  general initialization code accesses objects only
         visible to the current function.

     2.  The  general  initialization  code  is  too  large  to
         warrant duplication.

     3.  The  code  to  determine  the next operation is at the
         head of the loop.  (To  allow  it  to  be  reached  by
         continue statements, for example.)

           /* ... */
           goto first_time;
           for (;;) {
                   // determine next operation
                   /* ... */
                   if (need to reinitialize) {
                           // reinitialize-only code
                           /* ... */
                   first_time:
                           // general initialization code
                           /* ... */
                           continue;
                   }
                   // handle other operations
                   /* ... */
           }
Run Code Online (Sandbox Code Playgroud)

接下来,我们来看看for循环语句:

[#1]  Except for the behavior of a continue statement in the |
   loop body, the statement

           for ( clause-1 ; expr-2 ; expr-3 ) statement

   and the sequence of statements

           {
                   clause-1 ;
                   while ( expr-2 ) {
                           statement
                           expr-3 ;
                   }
           }
Run Code Online (Sandbox Code Playgroud)

把这两个问题放在一起告诉你,你正在跳过

i=0;
Run Code Online (Sandbox Code Playgroud)

进入一个while循环的中间.你会执行

...process data...
Run Code Online (Sandbox Code Playgroud)

然后

i++;
Run Code Online (Sandbox Code Playgroud)

在控制流程跳转到while/for循环中的测试之前

i<n;
Run Code Online (Sandbox Code Playgroud)


Ben*_*igt 5

是的,那是合法的.

你正在做的事情远不如Duff的设备那么丑陋,Duff的设备也符合标准.

正如@Alexandre所说,不要使用goto非平凡的构造函数来跳过变量声明.


我确信你并不期望在调用之间保留局部变量,因为自动变量生命周期是如此根本.如果你需要保留一些状态,那么functor(函数对象)将是一个不错的选择(在C++中).C++ 0x lambda语法使它们更容易构建.在C中,您将别无选择,只能将状态存储到调用者通过指针传入的某个状态块中.

  • @Sergey,@Sjoerd:相关事实是 Duff 的设备也会跳到循环中间。它很丑陋,因为“switch”(“case”标签)和循环的语法结构混合在一起。这也是它的美丽之处:) (3认同)
  • Duff的设备使用**开关**,这是goto的一种形式.托尼老虎:我已经用这些解决方案背后的一些原因更新了初始问题. (2认同)