仅遍历第一个和最后一个元素

时间:2015-11-20 00:24:09

标签: c loops for-loop

给定N = 1个元素,只处理第一个(0)和最后一个(N-1)元素。

但是,如果N-1,则只处理单个元素一次。

使用一个或两次运行的循环,可以避免重复循环体。如果有可行的方法,那么它对源代码大小有好处。它也可能对机器代码大小有好处,如果循环体很大,并且编译器不会最终复制它。

我尝试按N=1递增,但在for (i = 0 ; i < N ; i += (N - 1)) (永远循环)时无效。是否有解决此问题的技巧(反向循环f.i)?

#define forEachLglBound(i_,j_,k_)                                   \
        for(Int i_ = 0;i_ < NPX;i_+=((NPX>1) ? (NPX-1) : 1))        \
            for(Int j_ = 0;j_ < NPY;j_+=((NPY>1) ? (NPY-1) : 1))    \
                for(Int k_ = 0;k_ < NPZ;k_+=((NPZ>1) ? (NPZ-1) : 1))

编辑:

我原来的问题涉及x,y,z方向的三个嵌套循环,这就是为什么我不能只处理elem [0])和elem [N-1]。现在我有以下

getIntInput()

4 个答案:

答案 0 :(得分:7)

以下几行怎么样?与原始解决方案非常接近(文字!)。

for (i = 0 ; i < N ; i += (N > 1) ? N-1 : 1)

答案 1 :(得分:4)

如果可以将循环体分解为函数或宏,可能最可读的方式是:

process( arr[0] );
if (N-1 != 0)
    process( arr[N-1] );

如果这不是一个选项,或者您认为其中一个循环结构足够可读:

XOR可以在0和XOR值之间切换变量。

int i=0;
do {
    process(arr[i]);
} while(i ^= (N-1));  // xor to toggle, but stays zero if N-1 is zero

编译为比任何其他选项as you can see on godbolt更好的asm。我从其他答案中包含了一些想法,包括简单的if(当复制操作很便宜时,它很好。)

xor版本在三重嵌套循环中保持良好运行(请参阅godbolt链接底部的while_xor_triple函数)。

不使用xor,我认为这个循环具有中等可读性:

int i=0;
do {
    process( arr[i] );
} while( (i!=N-1) && (i=N-1) );

如果i尚未N-1,请将其设置为该值并重做循环。这应该使编译器可以轻松有效地进行测试,而不必计算除N-1之外的任何表达式。不过,gcc仍会分别对&&的两个操作数进行测试和分支,但开销比其他一些答案少。

第二个while循环可以编译成这样的东西(但遗憾的是没有,因为gcc没有做我前两个insn的诡计):

    xor   edx, edx
.repeat:
    mov   ecx, edx
      ... loop body using i (ecx)
    mov   edx, [N]
    dec   edx     ; edx = N-1
    cmp   ecx, edx
    jne .repeat

在考虑如何在asm中完成时,我想到了XOR的想法。 IDK,如果智能编译器可以从while(i!=N-1 && i=N-1)版本生成此输出,但它肯定更好:

    xor   ecx, ecx
.repeat:
      ... loop body using i (ecx)
    mov   edx, [N]
    dec   edx        ; edx = N-1
    xor   ecx, edx   ; i ^= N-1
    jnz .repeat      ; jump if the last result wasn't zero

如果N-1存储在寄存器或内存中,则mov/dec即时计算它会消失。

答案 2 :(得分:3)

array(
    'id'        => 'blogdescription',
    'type'      => 'text',
    'title'     => 'Blog Description',
    'default'   => '',
    'compiler'  => true,
),

for ( i = 0, repeat = 0; repeat < 2 && repeat < N; repeat++, i = N-1 )

答案 3 :(得分:-1)

这个怎么样,虽然不必使用for loop,但这只是一种简单易懂的方法。

for (int first = 0, last = N - 1;;) {
     // the stuff use first
     if (first != last) {
     // the stuff use last
     }
     break;
}