C 为嵌套循环声明虚拟变量的更好方法是什么?

C 为嵌套循环声明虚拟变量的更好方法是什么?,c,nested-loops,C,Nested Loops,由于源代码中的文本字符较少,方法1的优点是文件大小略小: int i, j; for (i = 0; i < numRows; i++) for (j = 0; j < numCols; j++) //<some code here> inti,j; 对于(i=0;i

由于源代码中的文本字符较少,方法1的优点是文件大小略小:

int i, j;
for (i = 0; i < numRows; i++)
    for (j = 0; j < numCols; j++)
    //<some code here>
inti,j;
对于(i=0;i
  • 方法2的优点是局部变量的范围较小

    int i;
    for (i = 0; i < numRows; i++)
    {
        int j;
        for (j = 0; j < numCols; j++)
        //<some code here>
    }
    
    inti;
    对于(i=0;i
  • 即使在今天的现代计算机中,优化的差异可以忽略不计,哪种方法被认为是“更好”的代码


    编辑以澄清此问题不是重复问题:

    此问题基于当前的C11标准,该标准不允许使用以下语法:

    for (int i = 0; i < numRows; i++)
    
    for(int i=0;i
    <>在C++和C99中,这种语法是完全可以接受的,而C11不允许在<<代码> < < /C> >语句> < /P>中进行变量声明。
    编辑以更正错误信息:


    我认为我使用的是C11,因为我最近从代码块下载了编译器,所以我说C11不允许在
    for
    语句中声明变量。但事实证明我实际上使用的是C90,这是我问题的根源。

    第二种方法也是最好的方法

  • 它可以使用低内存
  • 如果在任何其他循环中需要,允许再次使用相同的变量

  • 对于纯粹的紧凑性和范围限制,我将使用:

    for (size_t i = 0; i < numRows; i++) {
        for (size_t j = 0; j < numCols; j++) {
        //<some code here>
        }
    }
    
    (大小i=0;i{ 对于(大小j=0;j 注意
    size\u t
    用于数组索引。
    size\u t
    类型是保证能够保存任何数组索引的
    无符号
    整数类型。只是样式问题,但我也建议在所有循环体周围使用大括号。这使得您不太可能因为不可避免的更新和更改而破坏代码


    通过养成这样声明具有块作用域的循环变量的习惯,您可以强迫自己选择在代码的其他地方使用存储在循环变量中的值。

    这似乎是一个品味问题,而不是有任何明确的答案,但我将给出我的意见:

    考虑到当前的计算机,保存几个字符的源代码太微不足道了,甚至连想都不敢想。事实上,我想我会说,即使在1976年我在VAX11/780上学习C语言的时候

    我倾向于第二个示例,因为当前的首选项是声明尽可能接近第一次使用的变量。在C++中,甚至可以将循环变量的声明放入for语句:

    for (int i = 0; i < numRows; i++) {
       for (int j = 0; j < numCols; j++) {
          ...
       }
    }
    
    for(int i=0;i

    但这仍然只是一个品味问题:相信如果变量的声明接近其用途,程序将更具可读性。

    这两种方法都不是首选方法

    两个常见的编码准则是:(1)确保变量的存在时间不会超过需要的时间;(2)不要将变量用于一件以上的事情。遵循这样的指导原则可以减少(通常,但并非总是)意外使用变量,从而避免出现微妙的编程错误

    在第一种情况下,
    i
    j
    继续存在,直到封闭范围结束-这意味着它们在循环完成后存在。这最大限度地提高了后续代码(在该封闭范围内)意外重用
    i
    j
    用于其他目的(例如,当意图使用另一个变量时)的可能性。这样的bug通常很难找到

    第二种情况也有同样的问题,只是
    i
    。即使有一个变量有这样的问题也是坏消息

    我可能会使用这样的构造

    // unintentionally using i or j here will cause a compilation error
    
    for (int i = 0; i < numRows; i++)
    {
        // unintentionally using j here will cause a compilation error
    
        for (int j = 0; j < numCols; j++)
        {
           //<some code here>
        }
    
        // unintentionally using j here will cause a compilation error
    }
    
    // unintentionally using i or j here will cause a compilation error
    
    //无意中在此处使用i或j将导致编译错误
    对于(int i=0;i
    (我插入的注释使这一点更加难以理解,但在实践中通常不需要这样的注释)

    这可确保外部环路外不存在
    i
    not
    j
    。这也意味着
    j
    不能意外地用于外循环。实际上,当打算输入
    i
    时(反之亦然),很容易输入
    i
    ——例如,它们在QWERTY键盘上靠得很近
    i
    j
    在视觉上看起来也非常相似,因此视觉代码检查通常会忽略这些错误。然而,使用这样的方法,编译器将检测到此类打字错误。如果有选择的话,最好是让编译器拾取错误,而不是让人很难找到错误


    当然,这并不能防止内部循环中对
    i
    j
    的误用或交换——但这也是指导方针经常鼓励使用比
    i
    j
    更具信息性的名称的原因之一——误用视觉上不同的名称更容易被普通人察觉。

    它真的会使用更少的内存吗?我的理解是,大多数编译器都会自动在循环中移动变量。@tod的可能重复:您建议的重复不是一个错误的答案-除非它被标记,而不是。这使得它作为C问题的复制品不到100%。这些信息基本上仍然有效——但令人惊讶的是,没有讨论为循环中定义的
    字符串调用的构造函数和析构函数。@FridaySky:waddya mean?那些是蜜蜂