2012-08-08 59 views
1

在我当前的项目中,我偶然发现了一个奇怪的现象,其中嵌套的for循环只会执行一次内循环,然后停止。即使仔细检查了所有涉及的变量,外部for循环仍然没有正当理由终止。唯一让这个结构与我的程序中包含的其他for循环不同的事实是,counter变量作为参数传递给包含循环的函数,并且从不复制到任何地方。For循环功能参数在C++中的奇怪

所以决定测试,如果该问题可被再现:

#include <stdio.h> 

void someFunction(int x, int y, int width, int length) 
{ 
    int endX = x+width; 
    int endY = y+length; 

    printf("x will not exceed: %i\n", endX); 
    printf("y will not exceed: %i\n", endY); 

    for(; x < endX; x++) 
    { 
     for(; y < endY; y++) 
     { 
      printf("(%i, %i)\n", x, y); 
     } 
    } 
} 

int main(int argc, const char *argv[]) 
{ 
    someFunction(1, 1, 5, 5); 
    return 0; 
} 

在执行时,但是,应用程序的输出从直观厚望不同:

x will not exceed: 6 
y will not exceed: 6 
(1, 1) 
(1, 2) 
(1, 3) 
(1, 4) 
(1, 5) 

的行为是类似的,当x和y被切换,但y变量永远不会增加。通过简单地声明一个新变量作为每个循环的计数器即可解决问题。

但为什么会发生这种情况?是否因特定原因而被禁止?编译器是否会禁用某些参数的修改,如果是这样,为什么它只与一个变量一起工作,而不是另一个变量?

提供的源代码是用GCC/G ++ 4.5.3编译的,没有任何特殊的优化标志。

回答

13

y永远不会在x循环内重置,所以一旦它在第一次通过时超出边界,它将永远超出界限。

+0

嗯,这是很简单的。现在猜猜这是我的就寝时间。 – 2012-08-08 18:26:07

2

由于xy也存在于循环之外,并且由于循环没有设置它们的初始值,所以即使在重用时它们也保留最后一个值。 这尤其是关于您的y,它不会在y循环退出后回退到初始值。

为避免此类问题,请避免将循环外部的变量用作索引。

void someFunction(const int x, const int y, const int width, const int length) 
{ 
    int endX = x+width; 
    int endY = y+length; 

    printf("x will not exceed: %i\n", endX); 
    printf("y will not exceed: %i\n", endY); 

    for(int ix=x; ix < endX; ++ix) 
    { 
     for(int iy=0; iy < endY; ++iy) 
     { 
      printf("(%i, %i)\n", ix, iy); 
     } 
    } 
} 

但是,通过使参数为const,我们确保我们不会触摸它们,即使是错误的。然后我们使用本地ix和iy来处理迭代。

另外,除非您必须出于某种其他原因,否则请避免使用后缀增量,并使用前缀。在使用整数之前,这并不是一个大的改变,但是使用更复杂的变量可以改变它们。

如果避免像C程序员那样编码,这也是一个好主意(因为您将问题标记为C++而不是C)。

惯用C++相当于是这样的:

#include <iostream> 

void someFunction(const int& x, const int& y, const int& width, const int& length) 
{ 
    const int endX = x+width; 
    const int endY = y+length; 

    std::cout << "x will not exceed: " << endX << std::endl; 
    std::cout << "y will not exceed: " << endY << std::endl; 

    for(int ix=x; ix < endX; ++ix) 
    { 
     for(int iy=y; iy < endY; ++iy) 
     { 
      std::cout << '('<<ix<<", "<<iy<<')'<< std::endl;  
     } 
    } 
} 

int main() 
{ 
    someFunction(1, 1, 5, 5); 
    return 0; 
}