颠覆传统 goto 规则 的 MS VC 2010

tongshou 2019-03-20 01:16:56

下面例子可以在MSVC 2010正常编译、然后运行得结果。
goto 语句从下面一个循环 跳到 上面一个循环的Lab 处 (从外到内 !) 这是不是一个BUG ?

好像从传统goto 规则来讲是 违规吧?
现在的感觉是 晕!


void test()
{
int n=123;
int a=0;
int b=0;
int xNo=0;


for( int k=0; k<3; k++) {
int d = 888;

Lab:
d++;
a++;

if (xNo==3) {
return;
}
cgf_iprinn(a, "a=");
cgf_iprinn(k, "k=");
cgf_iprinn(d, "d=");
}

for( int j=0; j<n; j++) {
b++;
if (j==8) {
xNo++;
cgf_sprinn(xNo, "=========");
cgf_iprinn(xNo, "\nxNo=");
goto Lab;
}
}
}


运行结果
a=1
k=0
d=889
a=2
k=1
d=889
a=3
k=2
d=889
=========
xNo=1
a=4
k=3
d=890
=========
xNo=2
a=5
k=4
d=891
=========
xNo=3
...全文
358 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
测试:


//test.c, test.cpp
#include <stdio.h>
void test()
{
int n = 123;
int a = 0;
int b = 0;
int xNo = 0;


for (int k = 0; k < 3; k++) {
int d = 888;

Lab:
d++;
a++;

if (xNo == 3) {
return;
}
printf("a=%d\n",a);
printf("k=%d\n",k);
printf("d=%d\n",d);
}

for (int j = 0; j < n; j++) {
b++;
if (j == 8) {
xNo++;
printf("=========\n");
printf("xNo=%d\n", xNo);
goto Lab;
}
}
}

int main()
{
test();
}



GCC、VC2017 C 模式test.c编译通过可以运行。

$ ./a.exe
a=1
k=0
d=889
a=2
k=1
d=889
a=3
k=2
d=889
=========
xNo=1
a=4
k=3
d=890
=========
xNo=2
a=5
k=4
d=891
=========
xNo=3


G++ 直接挂了

g++ t.cpp
t.cpp: In function 'void test()':
t.cpp:13:2: error: jump to label 'Lab' [-fpermissive]
Lab:
^~~
t.cpp:31:9: note: from here
goto Lab;
^~~
t.cpp:11:7: note: skips initialization of 'int d'
int d = 888;
^
t.cpp:10:11: note: skips initialization of 'int k'
for (int k = 0; k < 3; k++) {
^



VC2017 C++模式,直接报错:

1>------ 已启动生成: 项目: test, 配置: Debug Win32 ------
1>t.cpp
1>c:\users\user\source\repos\test\test\t.cpp(31): error C2362: “goto k”跳过了“Lab”的初始化操作
1>c:\users\user\source\repos\test\test\t.cpp(10): note: 参见“k”的声明
1>c:\users\user\source\repos\test\test\t.cpp(13): note: 参见“Lab”的声明
1>c:\users\user\source\repos\test\test\t.cpp(31): error C2362: “goto d”跳过了“Lab”的初始化操作
1>c:\users\user\source\repos\test\test\t.cpp(11): note: 参见“d”的声明
1>c:\users\user\source\repos\test\test\t.cpp(13): note: 参见“Lab”的声明
1>已完成生成项目“test.vcxproj”的操作 - 失败。
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========


看起来,C是最接近汇编的东西了。对变量生存域比较死板,检查也不够。
C++,基本新标准已经把goto绑定在当前上下文里了,只要影响到生存区,就无法编译。
  • 打赏
  • 举报
回复


这个取决于编译器的不同、优化开关的不同哦。如果想当然的变成汇编,其实可以理解输出的。但是,在很多Release版或者-O3 expencive 之类的优化下,结果就不一定了。
天外怪魔 2019-03-25
  • 打赏
  • 举报
回复
不要用goto,除非你想离职,想害人。
worldy 2019-03-24
  • 打赏
  • 举报
回复
这个应该是个BUG,这样goto回去,起码k应该是个随机数
WJN92 2019-03-22
  • 打赏
  • 举报
回复
引用 4 楼 tongshou 的回复:
对C/C++语言来说确实逻辑很奇怪。对Python来说,好像是闭包特性。
不过,现在看来,在C/C++的{...}区域里的临时变量, 如果是基本类型,虽然在{...}外不能触及,但是在运行{...}后还是保留完整。
如果在{...}里有类对象,还是 goto 不进去。


但是在优化后就不一定了,临时变量有可能放在寄存器里面。
做实验可以,但是正常写代码应该没这个需要呀
bluesen 2019-03-20
  • 打赏
  • 举报
回复
我很好奇,谁会这么无聊goto到前面的循环内?
tongshou 2019-03-20
  • 打赏
  • 举报
回复
对C/C++语言来说确实逻辑很奇怪。对Python来说,好像是闭包特性。
不过,现在看来,在C/C++的{...}区域里的临时变量, 如果是基本类型,虽然在{...}外不能触及,但是在运行{...}后还是保留完整。
如果在{...}里有类对象,还是 goto 不进去。

WJN92 2019-03-20
  • 打赏
  • 举报
回复
这个逻辑很奇怪
tongshou 2019-03-20
  • 打赏
  • 举报
回复
在其他程序语言里好像有个类似特性:在Python里 用关键字yield。
对传统的C/C++来说,好像是无聊之举。如果C/C++这里不算BUG,编程效果可能不输 Python (^_^)



16,466

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧