在玩代码时,我注意到一个奇怪的行为,我不知道如何解释背后的逻辑
void foo(int n)
{
int m = n;
while (--n > 0)
{
switch (n)
{
case -1:
case 0:
for (int j = 0; j < m; ++j)
default:
printf(":-)");
break;
}
}
}
int main()
{
foo(10);
return 0;
}
我希望printf
执行10
次。然后我看到它继续运行(想象是100000而不是10),并且假设开发人员(VS)将中的
(这是意料之中的),因此每次进入printf
解释为switch
时输出都是n
次。
但后来证明j
从未初始化。
所以我的问题是为什么?这是一种未定义的行为吗?这不是一个标准的代码吗?
switch
块实际上是一组美化的goto
语句。不同的案例没有给代码引入作用域或任何逻辑结构。它们实际上只是switch
语句要跳转到的目标。
在此程序中,default:
标签位于嵌套的for
循环内。当default
大小写被命中时,程序在循环内跳转,就好像那里有goto
语句一样。开关
块等效于:
if (n == -1 || n == 0) {
goto before_loop;
}
else {
goto inside_loop;
}
before_loop:
for (int j = 0; j < m; ++j) {
inside_loop:
printf(":-)");
}
这是危险的,因为跳转到inside_loop:
会跳过j=0
。正如您所观察到的,j
仍然声明了,但没有初始化,访问它会导致未定义的行为。
default
只是一个标签(如果n
不是-1或0,则代码跳转到的地址)。因此,当n
不是-1或0时,流进入for
循环的主体,跳过j
的初始化。您也可以编写与此相同的代码,因此这里发生的事情会更清楚:
int m = n;
while (--n > 0)
{
switch (n)
{
case -1:
case 0:
for (int j = 0; j < m; ++j)
{
default: printf(":-)");
}
break;
}
}
(注意,正如@Alagner在评论中提到的,它不会用C++编译器编译,但可以用C语言完美地编译,所以这足以说明我的观点并解释代码的外观)。
所以是的,因为j
是未初始化的,所以它是未定义的行为。如果启用编译器警告,它将对您发出警告(https://godbolt.org/z/rzgrap):
warning: 'j' may be used uninitialized in this function [-Wmaybe-uninitialized]
12 | for (int j = 0; j < m; ++j)
| ^
我在运行Windows XP sp3的计算机上安装了Java 6和Java 7。我已在计算机中的环境变量(path、JAVA_HOME)中输入path- java-版本 我还是收到下面的短信 Java版本"1.7.0_09"Java(TM)SE运行时环境(构建1.7.0_09-b05)JavaHotSpot(TM)客户端VM(构建23.5-b02,混合模式,共享) 然而,当我尝试 javac-版本
我有 我想要 在JS我可以做 像这样简单的方法之一 围棋里有这样的东西吗?
问题内容: 目前,我正在此站点上抓取图表图表信息。要抓取信息,我需要为有很多镜头的情况做一个for循环。我可以通过单击“ Team Stats”并找到射门次数来找到射门次数。 我想做出适当的选择而不必找出拍摄数量。 我目前正在做什么: 任何帮助将不胜感激。请让我知道是否需要进一步的信息。 问题答案: 我不确定您的变量k是什么意思。 我从所有评论中获得了建议。
问题内容: 以下两个循环之间的性能差异(如果有)是什么? 和 问题答案: 版本1.5中引入的for-each循环通过完全隐藏迭代器或index变量,消除了混乱和出错的机会。结果成语同样适用于集合和数组: 当你看到冒号(:)时,将其读为“ in”。因此,上面的循环读为“对于元素中的每个元素e”。请注意,即使对于数组,使用for-each循环也不会降低性能。实际上,在某些情况下,它可能只比普通的for
我想有开关情况循环我的九个菜单,在那里我可以在任何给定的一个和菜单跳转到下一个随机选择,现在它目前旋转的顺序,无论我在哪里点击。
我有一个非常基本的函数,它搜索的数组列表,并返回与传递给它的参数匹配的帐户。但是,一旦抛出CustomerAccountNotFoundException,我的for循环就会中断。 我通过在异常后打印的值来测试这一点,该值一直被重置为0。如何在抛出异常后继续循环?我希望每次帐户不匹配时都抛出它,当它匹配时返回帐户。我还尝试过但不起作用。