给定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()
答案 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;
}