32位整数的二进制表示

时间:2017-10-06 03:36:08

标签: c binary int

我是c编程的新手,我想弄清楚有关比特的更多信息,二进制e.c.t

例如,我有三个int变量m1 = 255或11111111二进制; m2 = 255或11111111(二进制,m3 = 255或11111111,二进制,m4 = 0或00000000)。我试图将所有主题放在单个int变量temp中。像这样的东西(11111111 11111111 11111111 00000000) 这是我的一段代码:

int x1;  
unsigned char x2;  
unsigned char x3;
unsigned char x4;
int temp;
        x1 = x1|m1;
        printf("x1:%d\n", x1);
        x2 = x2|m2;
        printf("x2:%d\n", x2);
        temp = x1<<8;
        printf("temp:%d\n", temp);
        temp = temp|x2;
        printf("temp:%d\n", temp);
        x3 = x3|m3;
        printf("x3:%d\n", x3);
        temp = temp<<8;
        printf("temp:%d\n", temp);
        temp = temp|x3;
        printf("temp:%d\n", temp);
        x4 = x4|m4;
        printf("x4:%d\n", x4);
        temp = temp<<8;
        printf("temp:%d\n", x1);
        temp = temp|x4;
        printf("%d\n", temp);

我在这里使用左移和OR运算符。但是我的输出有点奇怪。 (我打印出每一步以找出问题所在。)

我得到了下一个输出:

X1:255

X2:255

温度:65280

温度:65535

X3:255

温度:16776960

温度:16777215

X4:0

温度:-256

温度:-256

一切都很好,直到温度变为-256,我不知道为什么。 我感谢任何帮助!谢谢!

2 个答案:

答案 0 :(得分:1)

您正在使用%d格式,并将变量视为有符号整数,您需要使用%u并将变量类型更改为无符号。

unsigned char x1;
unsigned int temp;

答案 1 :(得分:1)

你真的在C中有几个选择。首先,你试图做的是以下几点。 (注意:您应该包含stdint.h并使用uint32_t保证宽度值而不是int)您的问题围绕通过OR'ing 未初始化来调用未定义行为,并且无法正确移动x1, ..., x4的值。

要做你想要做的事情,你可以:

#include <stdio.h>

int main (void) {

    unsigned int x1 = 0, x2 = 0, x3 = 0, x4 = 0;  
    unsigned char m1, m2, m3, m4 = 0;

    m1 = m2 = m3 = 255;

    x1 |= m1;
    x2 |= ((unsigned)m2 << 8);
    x3 |= ((unsigned)m3 << 16);
    x4 = ((x1 | x2 | x3) << 8) | (unsigned)m4;

    printf("x1: %u\n", x1);
    printf("x2: %u\n", x2);
    printf("x3: %u\n", x3);
    printf("x4: %u\n", x4);

    return 0;
}

示例使用/输出

$ ./bin/shiftx
x1: 255
x2: 65280
x3: 16711680
x4: 4294967040

您还可以通过简单地使用两个变量和值255来简化逻辑。基本上,您将临时变量设置为255并向左移动8次,3次。您的最终值是前3个临时值的“或”,最后一个偏移为8,以使您的组合值与最低有效字节为零,例如

#include <stdio.h>
#include <stdint.h>

int main (void) {

    uint32_t tmp = 0, val = 0;  
    uint8_t m = 255;

    val = m;
    printf ("tmp1 : %u\n", val);

    tmp = val << 8;
    printf ("tmp2 : %u\n", tmp);
    val |= tmp;

    tmp <<= 8;
    printf ("tmp3 : %u\n", tmp);
    val |= tmp;

    tmp <<= 8;
    printf ("tmp4 : %u\n", tmp);

    val <<= 8;
    printf ("val  : %u\n", val);

    return 0;
}

示例使用/输出

$ ./bin/shift1var
tmp1 : 255
tmp2 : 65280
tmp3 : 16711680
tmp4 : 4278190080
val  : 4294967040

改进版本可以在unionbitfield struct值之间使用uint32_t,无论架构如何,都可以保证32-bit宽度。例如,您可以:

#include <stdio.h>
#include <stdint.h>

typedef union {
    struct {
        uint32_t a : 8,
                 b : 8,
                 c : 8,
                 d : 8;
    } bits;
    uint32_t value;
} bitunion;

int main (void) {

    bitunion bu = { .bits = {.a = 0, .b = 255, .c = 255, .d = 255} };

    printf ("bu.bits.a: %u\n", bu.bits.a);
    printf ("bu.bits.b: %u\n", bu.bits.b << 8);
    printf ("bu.bits.c: %u\n", bu.bits.c << 16);
    printf ("bu.bits.d: %u\n", bu.bits.d << 24);
    printf ("value    : %u\n", bu.value);     

    return 0;
}

注意:位域由d-c-b-a个字节组成)

示例使用/输出

$ ./bin/shiftxstruct
bu.bits.a: 0
bu.bits.b: 65280
bu.bits.c: 16711680
bu.bits.d: 4278190080
value    : 4294967040

现在,不要认为这是实现这一目标的唯一方法。只要准确计算最终值中的字节,就可以使用移位和OR的任意组合。仔细看看,如果您有其他问题,请告诉我。