10

我有一个 C 数组,如:

char byte_array[10];

另一个充当面具的角色:

char byte_mask[10];

我想在每个字节上使用按位运算得到另一个数组,该数组是第一个数组加上第二个数组的结果。

最有效的方法是什么?

谢谢你的回答。

4

3 回答 3

15
for ( i = 10 ; i-- > 0 ; )
    result_array[i] = byte_array[i] & byte_mask[i];
  • 向后预加载处理器缓存线。
  • 在比较中包含减量可以节省一些指令。

这适用于所有阵列和处理器。但是,如果您知道您的数组是字对齐的,那么更快的方法是转换为更大的类型并执行相同的计算。

例如,让我们说n=16而不是n=10. 那么这会更快:

uint32_t* input32 = (uint32_t*)byte_array;
uint32_t* mask32 = (uint32_t*)byte_mask;
uint32_t* result32 = (uint32_t*)result_array;
for ( i = 4 ; i-- > 0 ; )
    result32[i] = input32[i] & mask32[i];

(当然,你需要一个正确的类型uint32_t,如果n不是 2 的幂,你需要清理开头和/或结尾,以便对齐 32 位内容。)

变化:这个问题特别要求将结果放在一个单独的数组中,但是几乎可以肯定的是,就地修改输入数组会更快。

于 2009-03-20T22:53:38.350 回答
5

如果你想让它更快,请确保 byte_array 的长度是 4 的倍数(在 64 位机器上为 8),然后:

char byte_array[12];
char byte_mask[12];
/* Checks for proper alignment */
assert(((unsigned int)(void *)byte_array) & 3 == 0);
assert(((unsigned int)(void *)byte_mask) & 3 == 0);
for (i = 0; i < (10+3)/4; i++) {
  ((unsigned int *)(byte_array))[i] &= ((unsigned int *)(byte_mask))[i];
}

这比逐字节执行要快得多。

(请注意,这是就地突变;如果您还想保留原始的 byte_array,那么您显然需要将结果存储在另一个数组中。)

于 2009-03-20T22:55:58.080 回答
1
\#define CHAR_ARRAY_SIZE    (10)
\#define INT_ARRAY_SIZE     ((CHAR_ARRAY_SIZE/ (sizeof (unsigned int)) + 1)

typedef union _arr_tag_ {

    char          byte_array [CHAR_ARRAY_SIZE];
    unsigned int  int_array [INT_ARRAY_SIZE]; 

} arr_tag;

现在 int_array 用于掩蔽。这可能适用于 32 位和 64 位处理器。

arr_tag arr_src, arr_result, arr_mask;

for (int i = 0; i < INT_ARRAY_SIZE; i ++) {
    arr_result.int_array [i] = arr_src.int_array[i] & arr_mask.int_array [i];
}

试试这个,代码可能看起来也很干净。

于 2009-03-21T01:05:08.597 回答