unsigned char 到 8 个原始位的 unsigned char 数组

Posted

技术标签:

【中文标题】unsigned char 到 8 个原始位的 unsigned char 数组【英文标题】:unsigned char to unsigned char array of 8 original bits 【发布时间】:2014-11-27 20:25:55 【问题描述】:

我正在尝试获取给定的 unsigned char 并将 8 位 值存储在大小为 8 的 unsigned char 数组中 (@987654321 @)。

所以给定无符号字符A

我想创建一个 unsigned char 数组,其中包含 0 1 0 0 0 0 0 1(每个索引一个数字)

实现这一目标的最有效方法是什么?顺便说一句,感恩节快乐!!

【问题讨论】:

使用ch & (1 << n) 选择一个位,然后相应地设置数组中的值 二进制和 (&) 以及移位以获得胜利。应该将其发布为答案而不是评论马特。 【参考方案1】:

最快的(不确定这是否是你所说的“有效”)的方式可能是这样的

void char2bits1(unsigned char c, unsigned char * bits) 
    int i;
    for(i=sizeof(unsigned char)*8; i; c>>=1) bits[--i] = c&1;

该函数将要转换的字符作为第一个参数,并用相应的位模式填充数组bits。它在我的笔记本电脑上运行时间为 2.6 ns。它假设 8 位字节,但不知道 char 有多少字节长,并且不需要预先将输入数组初始化为零。

我没想到这是最快的方法。我的第一次尝试是这样的:

void char2bits2(unsigned char c, unsigned char * bits) 
    for(;c;++bits,c>>=1) *bits = c&1;

我认为通过避免数组查找、按自然顺序循环(以与所请求的顺序相反的顺序生成位为代价)以及在 c 为零时立即停止(因此在调用函数之前,位数组需要进行零初始化)。但令我惊讶的是,这个版本的运行时间为 5.2 ns,是上面版本的两倍。

调查相应的程序集发现不同之处在于循环展开,这是在前一种情况下执行的,而不是在后一种情况下执行的。因此,这说明了现代编译器和现代 CPU 通常如何具有令人惊讶的性能特征。

编辑:如果您确实希望结果中的无符号字符是字符 '0''1',请使用此修改后的版本:

void char2bits3(unsigned char c, unsigned char * bits) 
    int i;
    for(i=sizeof(unsigned char)*8; i; c>>=1) bits[--i] = '0'+(c&1);

【讨论】:

【参考方案2】:

您可以按照建议使用位运算符。

#include <stdio.h>

main() 
    unsigned char input_data = 8;
    unsigned char array[8] = 0;
    int idx = sizeof(array) - 1;
    while (input_data > 0) 
        array[idx--] = input_data & 1;
        input_data /= 2; // or input_data >>= 1;
    

    for (unsigned long i = 0; i < sizeof(array); i++) 
        printf("%d, ", array[i]);
    

【讨论】:

为什么不简单的input_data &gt;&gt;= 1 因为很久以前,每个编译器都会像你写的input_data &gt;&gt;= 1;那样优化input_data /= 2;,通常最清楚/2那个移位操作,人们理解更好的除法移位,在这种情况下工作用位可能没什么问题。 我不同意。您在逻辑上所做的是将位移动到下一个位置,以便可以使用 &1 读取它。除以二只是一种模糊的书写方式。 我明白它在做什么。我不同意你关于什么是最清楚的。当您在逻辑上做的是除法时,请使用除法。当您在逻辑上做的是移位时,请使用移位操作。通过将其写为一个部门,您隐藏了操作的意图。仅仅因为您已阅读有关不滥用位移位进行除法的建议并不意味着您永远不应该使用位移位! 存储为 int?什么意思?【参考方案3】:

取值,右移并屏蔽它以仅保留低位。将低位的值添加到字符 '0' 中,得到 '0' 或 '1' 并将其写入数组:

unsigned char val = 65;
unsigned char valArr[8+1] = ;

for (int loop=0; loop<8; loop++)
    valArr[7-loop] = '0' + ((val>>loop)&1);

printf ("val = %s", valArr);

【讨论】:

以上是关于unsigned char 到 8 个原始位的 unsigned char 数组的主要内容,如果未能解决你的问题,请参考以下文章

unsign的问题

C ++中是否存在实际的8位整数数据类型

使用 char 或 unsigned char 数组存储原始数据更好吗?

uint8_t uint32_t 类型强制转换出错 以及 unsigned char 类型和 unsigned int 类型相互转化

单片机怎么通过串口发送unsigned int类型的数据?

unsigned char 与 char 有啥却别?何时适用