用于C中的循环测试用例

时间:2015-03-16 04:21:41

标签: c loops

最近我发现我在C方面的表现并不像我想象的那么好,在做一些快速评论时,我偶然发现了http://www.cs.princeton.edu/courses/archive/spr11/cos217/lectures/02CExamples.pdf>这里的小程序

第7页,它有

#include <stdio.h>
int main(void){
    int c, i;
    for (i=0; i<10; i++){
        c = getchar();
        putchar(c);
    }
    return 0;
}

问题是为什么在循环中使用i=0; i<10而不是i=1; i<=10

我一直认为这两种形式是相同的,只要i的值没有在后来的代码中使用,但显然我错过了一些东西。这是来自普林斯顿,我无法想象他们会犯这样的错误所以我测试了一些简单的案例,但它们似乎是相同的。现在我觉得真的很难不能回答这么简单的问题。我在网站上搜索和搜索,但没有找到任何东西。请帮忙。谢谢!

编辑:感谢大家现在回答,至少我知道没有任何重大差异。我实际上有一些编程经验,但由于我主要教自己,我以为我错过了一些明显的东西。再次感谢。

5 个答案:

答案 0 :(得分:2)

在给定的上下文中它们是相同的。如果您使用C访问数组(基于0 ...) - 我假设答案基本上是&#34;要保持一致&#34;

答案 1 :(得分:2)

  

为什么在循环中使用i=0; i<10而不是i=1; i<=10

这对您的计划没有任何影响。但是,如果要访问阵列,则需要使用第一个表单。第二种形式将导致未定义的行为。

int a[10];
int i;
for ( i = 1; i <= 10; ++i )
{
   a[i] = i*2;   // Problem when i == 10.
}

最好使用第一个表单在程序中保持一致。

答案 2 :(得分:1)

没有区别。任何现代编译器都会理解这两种形式都意味着循环需要执行十次,并且他们会找到最有效的方法。

答案 3 :(得分:1)

看看两个代码片段生成的汇编代码,编译器同样处理了两个片段。所以没有区别

void f1 () 
{
    int c, i;
    for (i=0; i<10; i++){
        c = getchar();
        putchar(c);
    }
}   
f1():
    pushq   %rbx
    movl    $10, %ebx
.L2:
    movq    stdin(%rip), %rdi
    call    _IO_getc
    movq    stdout(%rip), %rsi
    movl    %eax, %edi
    call    _IO_putc
    subl    $1, %ebx
    jne .L2
    popq    %rbx
    ret

void f2() 
{
    int c, i;
    for (i=1; i<=10; i++){
        c = getchar();
        putchar(c);
    }
}   
f2():
    pushq   %rbx
    movl    $10, %ebx
.L7:
    movq    stdin(%rip), %rdi
    call    _IO_getc
    movq    stdout(%rip), %rsi
    movl    %eax, %edi
    call    _IO_putc
    subl    $1, %ebx
    jne .L7
    popq    %rbx
    ret

答案 4 :(得分:1)

如果用一些在循环之前初始化的整数变量替换魔术常量10,则存在本质区别。 请考虑以下两个循环。

int n = SOME_VALUE;

for ( i = 0; i < n; i++ )
{
    /* ... */
}

int n = SOME_VALUE;

for ( i = 1; i <= n; i++ )
{
    /* ... */
}

现在因为一般情况下n可以分配任何值,那么第二个循环不等同于第一个循环。:)第二个循环是不安全的,可以是无限的。考虑将n设置为INT_MAX的情况。在这种情况下,当i达到此值时,INT_MAX条件i <= n将成立。结果i会递增,您可以i等于INT_MIN。 因为INT_MIN <= INT_MAX循环将重新迭代。:)

那么如何在一般情况下正确编写第二个循环?例如,您可以将其拆分为带条件的循环

for ( i = 1; i < n; i++ )
{
    /* ... */
}

然后在循环本身后重复循环体,其中i等于n。所以你会得到

for ( i = 1; i < n; i++ )
{
    /* body of the loop */
}

/* body of the loop as separate code snippet */

正确编写此循环而不拆分的另一种方法是以下

for ( i = 1, j = 0; i <= n && j != n; j = i++ )
{
    /* body of the loop */
}

通常程序员认为n永远不能等于INT_MAX,就像他们认为不会有2000年那样。:)