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:感谢所有评论过的人!
对所有评论者:)是的,我明白我不能跳过局部变量的初始化器,我必须i在每次调用时保存/恢复.
关于强大的原因:)这段代码必须实现反向通信接口.反向通信是一种试图避免使用函数指针的编码模式.有时,它有它,因为预计你遗留代码中使用会使用它.
不幸的是,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)
是的,那是合法的.
你正在做的事情远不如Duff的设备那么丑陋,Duff的设备也符合标准.
正如@Alexandre所说,不要使用goto非平凡的构造函数来跳过变量声明.
我确信你并不期望在调用之间保留局部变量,因为自动变量生命周期是如此根本.如果你需要保留一些状态,那么functor(函数对象)将是一个不错的选择(在C++中).C++ 0x lambda语法使它们更容易构建.在C中,您将别无选择,只能将状态存储到调用者通过指针传入的某个状态块中.