如果我理解您问题的两个部分 (1) 从 40-element 整数数组的 -1 & 1 值中确认您对 5 - unsigned char 值的位设置; (2) 输出每个5 - unsigned char 值的二进制表示,然后可以通过多种方式完成。为了在每个unsigned char 值中设置set 位,您只需将OR 与1 的当前值逐位左移 适当的数量来设置问题位。例如要在unsigned char v = 0; 中设置3rd-bit,您只需设置v |= 1<<2;
为所有 5 个 unsigned char 元素设置位的几种不同方法可以通过嵌套循环蛮力方法完成:
/* brute force nested loop approach */
for (i = 0; i < szarr; i++)
for (j = 0; j < CHAR_BIT; j++)
if (buf[i * CHAR_BIT + j] == 1) arr[i] |= (1 << j);
(其中szarr 是您的char arr[5] = {0}; 数组的sizeof *arr(或只是5,其中CHAR_BIT (limits.h) 定义char 中的位数(通常为8 ))
一种在效率方面具有优势的展开方法(尽管大多数当前的编译器会尝试采用积极优化的展开解决方案)。它更好地说明了正在发生的过程:
/* unrolled loop setting all bits in each unsigned char per loop */
for (i = 0; i < szbuf; i+=8) {
if (buf[ i ] == 1) arr[i/8] |= 1;
if (buf[i+1] == 1) arr[i/8] |= (1 << 1);
if (buf[i+2] == 1) arr[i/8] |= (1 << 2);
if (buf[i+3] == 1) arr[i/8] |= (1 << 3);
if (buf[i+4] == 1) arr[i/8] |= (1 << 4);
if (buf[i+5] == 1) arr[i/8] |= (1 << 5);
if (buf[i+6] == 1) arr[i/8] |= (1 << 6);
if (buf[i+7] == 1) arr[i/8] |= (1 << 7);
}
最后,您如何轻松查看每个无符号值的二进制表示来确认您的逻辑。与其他任何事情一样,您如何实现这一点也有很多变化。对于一般测试,我找到了一个简单的函数,它返回二进制字符串的char * 表示,填充到所需的长度,比几乎任何其他方法有用,因为它允许您保留正常的格式控制在单个printf 等内。
虽然unsigned 值不是 100% 必要的,但大多数硬件都同意 4-bytes 构成 int 和 unsigned。但是,由于可能存在变化,因此最好使用精确类型或使用简单的预处理器指令来确定 BITS_PER_LONG 的数量等。使用将处理填充 long unsigned 值的通用二进制打印例程,一个简单的测试在 32/64 位机器之间很有帮助。例如:
/* BITS_PER_LONG */
#if defined(__LP64__) || defined(_LP64)
# define BITS_PER_LONG 64
#else
# define BITS_PER_LONG 32
#endif
...
/** returns pointer to binary representation of 'v' zero padded to 'sz'.
* returns pointer to string contianing binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits.
*/
char *binpad (const unsigned long v, const size_t sz)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
register size_t i;
for (i = 0; i < sz; i++)
*--p = (v>>i & 1) ? '1' : '0';
return p;
}
现在将所有部分放在一起并组成一个40-element 数组,其中包含-1 或1 用于测试目的,您可以执行以下操作,并使用简单的编译器定义NESTED表示使用蛮力嵌套循环版本构建,如果没有给出定义,则使用展开版本:
#include <stdio.h>
/* CHAR_BIT */
#ifndef CHAR_BIT
# define CHAR_BIT 8
#endif
/* BITS_PER_LONG */
#if defined(__LP64__) || defined(_LP64)
# define BITS_PER_LONG 64
#else
# define BITS_PER_LONG 32
#endif
char *binpad (const unsigned long v, const size_t sz);
int main (void){
unsigned char buf[] = { -1, -1, 1, -1, -1, -1, 1, 1,
-1, 1, -1, -1, -1, 1, 1, -1,
1, -1, -1, -1, 1, 1, -1, -1,
-1, -1, -1, 1, 1, -1, -1, -1,
-1, -1, 1, 1, -1, -1, -1, 1 };
unsigned char arr[5] = {0};
unsigned i, szarr = (unsigned) sizeof arr;
#ifdef NESTED
unsigned j;
/* brute force nested loop approach */
for (i = 0; i < szarr; i++)
for (j = 0; j < CHAR_BIT; j++)
if (buf[i * CHAR_BIT + j] == 1) arr[i] |= (1 << j);
#else
unsigned szbuf = (unsigned) sizeof buf;
/* unrolled loop setting all bits in each unsigned char per loop */
for (i = 0; i < szbuf; i+=8) {
if (buf[ i ] == 1) arr[i/8] |= 1;
if (buf[i+1] == 1) arr[i/8] |= (1 << 1);
if (buf[i+2] == 1) arr[i/8] |= (1 << 2);
if (buf[i+3] == 1) arr[i/8] |= (1 << 3);
if (buf[i+4] == 1) arr[i/8] |= (1 << 4);
if (buf[i+5] == 1) arr[i/8] |= (1 << 5);
if (buf[i+6] == 1) arr[i/8] |= (1 << 6);
if (buf[i+7] == 1) arr[i/8] |= (1 << 7);
}
#endif
for (i = 0; i < szarr; i++) /* validate the bit settings */
printf (" arr[%2u] : %3u (%s)\n",
i, arr[i], binpad (arr[i], CHAR_BIT));
return 0;
}
/** returns pointer to binary representation of 'v' zero padded to 'sz'.
* returns pointer to string contianing binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits.
*/
char *binpad (const unsigned long v, const size_t sz)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
register size_t i;
for (i = 0; i < sz; i++)
*--p = (v>>i & 1) ? '1' : '0';
return p;
}
使用/输出示例
输出值适用于您的 5 个 unsigned char 数组元素中的每一个,显示根据 -1 和 1 的解释以及二进制创建的 十进制 值该数字的表示填充到8-chars:
$ ./bin/array_uc_bits
arr[ 0] : 196 (11000100)
arr[ 1] : 98 (01100010)
arr[ 2] : 49 (00110001)
arr[ 3] : 24 (00011000)
arr[ 4] : 140 (10001100)
查看所有答案和所有方法,如果您还有其他问题,请告诉我。
注意:如果您不熟悉如何在编译时设置像 NESTED 这样的标签定义,您所需要做的就是将其作为前面带有 -D 的选项传递,例如-DNESTED在命令行中传递会触发编译嵌套的蛮力代码,例如
$ gcc -Wall -Wextra -Ofast -DNESTED -o bin/array_uc_bits_nest array_uc_bits.c
就是所需要的。 (当然可以根据自己的喜好调整输入和输出名称。)