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

发布于 2024-12-13 09:55:08 字数 413 浏览 5 评论 0原文

假设有两个数组 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) 直接比较两个内存区域的结果,但我不知道是否可能。 非常感谢您的关注。

supposing to have two arrays a[N],b[N] containing only 0 and 1 values, is there a way to calculate c = a || b without a loop like the following (in 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];

I would want to calculate the result of (a || b) directly comparing the two memory areas, but i don't know if it's possible.
thank you very much for your attention.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

如若梦似彩虹 2024-12-20 09:55:08

由于按位或是必须应用于单个值的运算,因此我认为不存在。您是否有特定原因想要避免循环?如果这很麻烦,那么用它来创建一个函数就很容易了。

编辑:问题现在已更改为逻辑或,但我认为答案没有太大不同。

Since bitwise or is an operation that has to be applied to a single value, I don't think there is. Is there a particular reason you want to avoid the loop? If it's a hassle, making a function out of it is easy.

Edit: The question has now changed to logical OR, but I don't think the answer is much different.

揽月 2024-12-20 09:55:08

怎么样:

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

这会给你一个符号 c 数组。只需删除 c 变量声明即可。

How about:

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

This gives you a symbolic c-array. Just remove the c variable declaration.

筑梦 2024-12-20 09:55:08

您可以将字符数组转换为机器支持的最大整数,然后对整数进行 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);
}

You could typecast the character array to the largest integer that your machine supports, and then do the OR operation on the integers which would save you some instruction cycles. Note that you will have to choose your array size in multiples of the size of the integer you are using.

    #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);
}
童话 2024-12-20 09:55:08

过早的优化。在花费更多时间之前将其放入分析器中。编译器可能会代表您执行一些操作,例如展开循环或一次处理块。

premature optmization. put this in a profiler before spending any more time. The compiler might do stuff like unroll the loop or work on chunks at a time on your behalf.

疯狂的代价 2024-12-20 09:55:08

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

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 位,并且一个无符号的long long 至少可以容纳 64。

I can't imagine why you'd want to do so, but you could also turn the iteration into tail recursion:

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);
}

Probably a better alternative would be to encode the 0's and 1's as actual bits in an unsigned number, in which case you can use a bitwise or to do the job in a single operation:

unsigned long a, b, c;

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

c = a | b;

You're guaranteed that an unsigned long can hold at least 32 bits, and an unsigned long long can hold at least 64.

被翻牌 2024-12-20 09:55:08

如果这是针对 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]);
}

If this is for x86 then you can process 16 array elements at a time using SSE:

// 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]);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文