我是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,我不知道为什么。 我感谢任何帮助!谢谢!
答案 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
改进版本可以在union
和bitfield 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的任意组合。仔细看看,如果您有其他问题,请告诉我。