如何对数组指向的区域内存进行逻辑或运算

时间:2011-11-03 16:10:40

标签: c arrays for-loop logical-operators

假设有两个数组a [N],b [N]只包含0和1的值,有没有办法计算c = a || b没有像下面这样的循环(在C中)?

#define N 10
char a[N];
char b[N];
char c[N];


// suppose to do some operations on a and b so that 
// for each i a[i] == 0 or a[i] == 1
// and the same for b

// this is the loop i would want to avoid
int i;
for(i=0;i<N;i++)
     c[i] = a[i] || b[i];

我想计算(a || b)直接比较两个内存区域的结果,但我不知道是否可能。 非常感谢你的关注。

6 个答案:

答案 0 :(得分:4)

由于按位或是必须应用于单个值的操作,我认为没有。您是否有特殊原因要避免循环?如果这很麻烦,那就很容易做出一个功能。

编辑:问题现在已更改为逻辑OR,但我认为答案不同。

答案 1 :(得分:0)

怎么样:

#define c(index)    (a(index) || b(index))

这为您提供了一个符号c阵列。只需删除c变量声明。

答案 2 :(得分:0)

您可以将字符数组强制转换为机器支持的最大整数,然后对整数执行OR运算,这样可以节省一些指令周期。请注意,您必须以您正在使用的整数大小的倍数选择数组大小。

    #define LARGE_INTEGER unsigned long long

    #define ACTUAL_SIZE 10

    #define SIZEOF_LARGE_INT sizeof(LARGE_INTEGER)

    #define N (ACTUAL_SIZE + (SIZEOF_LARGE_INT - (ACTUAL_SIZE % SIZEOF_LARGE_INT)))

char a[N] = {0,1,0,1,0,1,1,1,1,1};
char b[N] = {1,0,1,0,1,0,1,0,1,0};
char c[N];

LARGE_INTEGER *pa, *pb, *pc;

int i;

for(i = 0; i < N; i = i + SIZEOF_LARGE_INT)
{
    pa = (LARGE_INTEGER*) &a[i];
    pb = (LARGE_INTEGER*) &b[i];
    pc = (LARGE_INTEGER*) &c[i];

    *pc = (*pa) | (*pb);
}

答案 3 :(得分:0)

<过早优化。在花费更多时间之前把它放在剖析器中。编译器可能会执行诸如展开循环或代表您一次处理块的操作。

答案 4 :(得分:0)

如果是x86,则可以使用SSE一次处理16个数组元素:

// NB: we're assuming:
//   - N is a multiple of 16
//   - a[], b[], and c[] are 16 byte aligned

for (int i = 0; i < N; i += 16)
{
    __m128i va = _mm_load_si128(&a[i]);
    __m128i vb = _mm_load_si128(&b[i]);
    __m128i vc;
#ifdef LOGICAL_OR // NB: only need these two lines if we are doing logical OR - omit for bitwise OR
    va = _mm_add_epi8(_mm_cmpeq_epi8(va, _mm_set1_epi8(0)), _mm_set1_epi8(1));
    vb = _mm_add_epi8(_mm_cmpeq_epi8(vb, _mm_set1_epi8(0)), _mm_set1_epi8(1));
#endif
    vc = _mm_or_si128(va, vb);
    _mm_store_si128(vc, &c[i]);
}

答案 5 :(得分:0)

我无法想象为什么你想要这样做,但你也可以把迭代变成尾递归:

int do_or(int n, int *a, int *b, int *c) { 
    if (0 == n)
       return;

    *c = *a || * b;
    do_or(n-1, a+1, b+1, c+1);
}

可能更好的选择是将0和1编码为无符号数中的实际位,在这种情况下,您可以使用按位or在单个操作中完成工作:

unsigned long a, b, c;

// code to set/clear bits in a and b elided

c = a | b;

您可以保证unsigned long至少可以保留32位,而unsigned long long至少可以保留64位。