【问题标题】:Reading characters on a bit level在位级别读取字符
【发布时间】:2011-01-12 05:52:55
【问题描述】:

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

此外,我还想以一种允许我输出它们是真还是假的方式读取这些位。

例如

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

我会发布一个我自己尝试过的想法,但我完全不知道,我仍在尝试使用 C,这是我第一次尝试以如此低的级别进行编程。

谢谢

【问题讨论】:

  • 你想要在 C 中还是在 C# 中?您放置的 .net3-5 标记将暗示 C#,但您也放置了一个不一致的 C 标记。
  • 这是一个有趣的练习!

标签: c binary bit-manipulation


【解决方案1】:

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

那么,您的朋友就是按位布尔运算符(&|^~)和移位运算符(<<>>)。例如,如果您的角色在变量 x 中,那么要获得第 5 位,您只需使用:((x >> 5) & 1)。移位运算符将值向右移动,删除五个低位并将您感兴趣的位移动到“最低位置”(也称为“最右边”)。与 1 的按位与只是将所有其他位设置为 0,因此结果值为 0 或 1,这是您的位。请注意,我从左有效(最右边)到最高有效(最左边)对位进行编号,我从零开始,而不是一。

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

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

您可能会注意到,由于我从右到左编号位,但您希望从左到右输出,因此循环索引必须减少。

请注意,根据 C 标准,unsigned char至少有 8 位,但可能有更多(现在,只有少数嵌入式 DSP 具有非 8 位的字符)。为了更加安全,请将其添加到代码开头附近(作为顶级声明):

#include <limits.h>
#if CHAR_BIT != 8
#error I need 8-bit bytes!
#endif

如果目标系统恰好是那些特殊的嵌入式 DSP 之一,这将阻止成功编译。作为注释上的注释,C标准中的术语“字节”表示“对应于unsigned char的基本内存单元”,因此,在C语言中,一个字节可能有超过八位(一个字节并不总是一个八位字节)。这是一个传统的混淆来源。

【讨论】:

    【解决方案2】:

    这可能不是最安全的方法 - 没有完整性/大小/类型检查 - 但它仍然可以工作。

    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
    • 已编辑 - 但你能检查一下吗,因为我的 C 不如我的 C++ 强大。
    • 我认为 OP 想要任何角色。
    • scanf 应该是scanf("%c", &amp;myChar);
    • 我以为c中没有一种叫做“bool”的类型?
    【解决方案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;
    }
    

    您不一定需要三个循环 - 如果需要,您可以将它们组合在一起,如果您只执行两种输出中的一种,那么您不需要数组,您可以使用每个位值,因为您将其屏蔽掉。但我认为这使事情分开,希望更容易理解。

    【讨论】:

    • +1 是一个完整的例子,这导致我删除了我自己的。其他任何人(除非顽固或愚蠢)都应该这样做;)
    • 非常彻底,不幸的是,当粘贴到空白源文件中时,出现 45 个错误,主要是语法错误和未声明的标识符。
    • 非常好,效果很好。也感谢您对解决方案的精彩解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 2015-08-18
    • 1970-01-01
    相关资源
    最近更新 更多