在位级读取字符

时间:2010-02-02 16:31:52

标签: c binary bit-manipulation

我希望能够从键盘输入一个字符,并以00000001格式显示所述密钥的二进制代码。

此外,我还希望以允许我输出的方式读取这些位,如果它们是真或假。

e.g。

01010101 = false,true,false,true,false,true,false,true

我会发表一个关于我是如何尝试自己做的想法,但我完全不知道,我还在尝试使用C,这是我第一次尝试这么低级别的编程。

三江源

3 个答案:

答案 0 :(得分:4)

这可能不是最安全的方式 - 没有理智/大小/类型检查 - 但它应该仍然有用。

unsigned char myBools[8];
char myChar;  

// get your character - this is not safe and you should
// use a better method to obtain input...
// cin >> myChar; <- C++
scanf("%c", &myChar);

// binary AND against each bit in the char and then
// cast the result. anything > 0 should resolve to 'true'
// and == 0 to 'false', but you could add a '> 1' check to be sure.
for(int i = 0; i < 8; ++i)
{
   myBools[i] = ( (myChar & (1 << i) > 0) ? 1 : 0 );
}

这将为你提供一个无符号字符数组 - 0或1(真或假) - 用于字符。

答案 1 :(得分:4)

对于位调整,使用无符号类型通常更安全,因为有符号负值的移位具有依赖于实现的效果。普通char可以是有符号或无符号的(传统上,它在MacIntosh平台上未签名,但在PC上签名)。因此,首先将角色转换为unsigned char类型。

然后,您的朋友是按位布尔运算符(&|^~)以及移位运算符(<<和{{ 1}})。例如,如果您的角色位于变量>>中,那么要获得第5位,您只需使用:x。移位运算符将值向右移动,丢弃五个低位并将您感兴趣的位移动到“最低位置”(又名“最右侧”)。按位AND与1简单地将所有其他位设置为0,因此结果值为0或1,这是您的位。请注意,我将从左有效位(最右边)到最高位(最左边)的位编号,我从零开始,而不是一个。

如果您认为您的字符是8位,则可以将代码编写为:

((x >> 5) & 1)

你可能会注意到,由于我从右到左编号,但你想从左到右输出,循环索引必须减少。

请注意,根据C标准,unsigned char x = (unsigned char)your_character; int i; for (i = 7; i >= 0; i --) { if (i != 7) printf(","); printf("%s", ((x >> i) & 1) ? "true" : "false"); } 至少八位但可能有更多(现在,只有极少数嵌入式DSP具有不是8位的字符) 。为了更加安全,请在代码的开头附近添加(作为顶级声明):

unsigned char

如果目标系统恰好是那些特殊的嵌入式DSP之一,这将阻止成功编译。作为注释的注释,C标准中的术语“字节”表示“对应于#include <limits.h> #if CHAR_BIT != 8 #error I need 8-bit bytes! #endif ”的基本存储单元,因此,在C语言中,一个字节可能具有多于8位(一个字节并不总是一个八位字节)。这是一个混乱的传统来源。

答案 2 :(得分:3)

此代码为C89:

/* we need this to use exit */
#include <stdlib.h>
/* we need this to use CHAR_BIT */
#include <limits.h>
/* we need this to use fgetc and printf */
#include <stdio.h>

int main() {
    /* Declare everything we need */
    int input, index;
    unsigned int mask;
    char inputchar;

    /* an array to store integers telling us the values of the individual bits.
       There are (almost) always 8 bits in a char, but it doesn't hurt to get into
       good habits early, and in C, the sizes of the basic types are different
       on different platforms. CHAR_BIT tells us the number of bits in a byte. 
     */
    int bits[CHAR_BIT];

    /* the simplest way to read a single character is fgetc, but note that
       the user will probably have to press "return", since input is generally 
       buffered */
    input = fgetc(stdin);
    printf("%d\n", input);

    /* Check for errors. In C, we must always check for errors */
    if (input == EOF) {
        printf("No character read\n");
        exit(1);
    }

    /* convert the value read from type int to type char. Not strictly needed,
       we can examine the bits of an int or a char, but here's how it's done. 
     */
    inputchar = input;

    /* the most common way to examine individual bits in a value is to use a 
       "mask" - in this case we have just 1 bit set, the most significant bit
       of a char. */
    mask = 1 << (CHAR_BIT - 1);

    /* this is a loop, index takes each value from 0 to CHAR_BIT-1 in turn,
       and we will read the bits from most significant to least significant. */
    for (index = 0; index < CHAR_BIT; ++index) {
        /* the bitwise-and operator & is how we use the mask.
           "inputchar & mask" will be 0 if the bit corresponding to the mask
           is 0, and non-zero if the bit is 1. ?: is the ternary conditional
           operator, and in C when you use an integer value in a boolean context,
           non-zero values are true. So we're converting any non-zero value to 1. 
         */
        bits[index] = (inputchar & mask) ? 1 : 0;

        /* output what we've done */
        printf("index %d, value %u\n", index, inputchar & mask);

        /* we need a new mask for the next bit */
        mask = mask >> 1;
    }

    /* output each bit as 0 or 1 */
    for (index = 0; index < CHAR_BIT; ++index) {
        printf("%d", bits[index]);
    }
    printf("\n");

    /* output each bit as "true" or "false" */
    for (index = 0; index < CHAR_BIT; ++index) {
        printf(bits[index] ? "true" : "false");
        /* fiddly part - we want a comma between each bit, but not at the end */
        if (index != CHAR_BIT - 1) printf(",");
    }
    printf("\n");
    return 0;
}

你不一定需要三个循环 - 你可以把它们组合在一起如果你想要的话,如果你只是做两种输出中的一种,那么你就不需要这个数组,你可以只使用每一个掩盖它时的位值。但我认为这会让事情分开,希望更容易理解。