int main()
{
unsigned char ptr[9];
uint16_t dat = 128, s;
int i, j = 1, k;
ptr[0] = ptr[0] & 0;
j = -1;
for(i = 0;i <= 15;i++)
{
if(i % 8 == 0)
j++;
s = dat << i;
if (s & (1 << 15))
ptr[j] |= 1 << (7 - i%8);
else
ptr[j] |= 0 << (7 - i%8);
}
j = -1;
s &= 0;
for(i = 0;i <= 15;i++)
{
if(i % 8 == 0)
j++;
s |= (ptr[j] & (1 << (7 - i%8))) << (15 - i); // <-----------
s |= (ptr[j] & (1 << i%8)) << (15 - i); // Correction
}
printf("%d", s);
return(0);
}
我试图将一个16字节的整数打包成一个字符数组,首先转换成二进制,然后逐位将它复制到数组中。但是,我在标记线上遇到了麻烦。我得到16834作为输出。我在这里做错了什么?
答案 0 :(得分:1)
如上所述,输出是不确定的,因为您从未将ptr[1]
设置为已知值。在我的Mac上,代码的这种微小变化(主要是添加了一些,标题,空格和printf()
语句):
#include <stdint.h>
#include <stdio.h>
int main(void)
{
unsigned char ptr[9];
uint16_t dat = 128, s;
int i, j = 1;
ptr[0] = ptr[0] & 0;
j = -1;
printf("0x%.2X 0x%.2X\n", ptr[0], ptr[1]);
for (i = 0; i <= 15; i++)
{
if (i % 8 == 0)
j++;
s = dat << i;
if (s & (1 << 15))
ptr[j] |= 1 << (7 - i % 8);
else
ptr[j] |= 0 << (7 - i % 8);
}
printf("0x%.2X 0x%.2X\n", ptr[0], ptr[1]);
j = -1;
s &= 0;
for (i = 0; i <= 15; i++)
{
if (i % 8 == 0)
j++;
s |= (ptr[j] & (1 << (7 - i % 8))) << (15 - i); // <-----------
}
printf("0x%.2X\n", s);
printf("%d\n", s);
return(0);
}
显示输出:
0x00 0xF4
0x00 0xF4
0x5510
21776
修改后将ptr[0] = ptr[0] & 0;
替换为ptr[0] = ptr[1] = 0;
,输出为:
0x00 0x00
0x00 0x80
0x4000
16384
你不幸的是你的机器将堆栈归零;你发现像未初始化的变量这样的错误要困难得多。
您选择128作为测试值会让生活变得困难;只有一个位集。如果我测试,我会使用一个独特的模式,如0x3CA5(C ++ 14二进制表示法中的0b0011'1100'1010'0101)。当我将代码更改为使用0x3CA5时,我得到输出:
0x00 0x00
0x3C 0xA5
0x5411
21521
好消息:第一个循环复制这些位,使得该数字的高位字节位于ptr[0]
,而低位字节位于ptr[1]
。坏消息:第二个循环似乎可怕地破坏了事情。
这是第二个循环的检测版本:
for (i = 0; i < 16; i++)
{
if (i % 8 == 0)
j++;
uint16_t s0 = s;
s |= (ptr[j] & (1 << (7 - i % 8))) << (15 - i); // <-----------
printf("i: %2d, j: %d, 7-i%%8: %d, ptr[j]: 0x%.2X, &val: 0x%.2X, "
"|val = 0x%.5X, s0: 0x%.4X, s: 0x%.4X\n",
i, j, 7 - i % 8, ptr[j], (1 << (7 - i % 8)),
(ptr[j] & (1 << (7 - i % 8))) << (15 - i),
s0, s);
}
输出结果为:
0x00 0x00
0x3C 0xA5
i: 0, j: 0, 7-i%8: 7, ptr[j]: 0x3C, &val: 0x80, |val = 0x00000, s0: 0x0000, s: 0x0000
i: 1, j: 0, 7-i%8: 6, ptr[j]: 0x3C, &val: 0x40, |val = 0x00000, s0: 0x0000, s: 0x0000
i: 2, j: 0, 7-i%8: 5, ptr[j]: 0x3C, &val: 0x20, |val = 0x40000, s0: 0x0000, s: 0x0000
i: 3, j: 0, 7-i%8: 4, ptr[j]: 0x3C, &val: 0x10, |val = 0x10000, s0: 0x0000, s: 0x0000
i: 4, j: 0, 7-i%8: 3, ptr[j]: 0x3C, &val: 0x08, |val = 0x04000, s0: 0x0000, s: 0x4000
i: 5, j: 0, 7-i%8: 2, ptr[j]: 0x3C, &val: 0x04, |val = 0x01000, s0: 0x4000, s: 0x5000
i: 6, j: 0, 7-i%8: 1, ptr[j]: 0x3C, &val: 0x02, |val = 0x00000, s0: 0x5000, s: 0x5000
i: 7, j: 0, 7-i%8: 0, ptr[j]: 0x3C, &val: 0x01, |val = 0x00000, s0: 0x5000, s: 0x5000
i: 8, j: 1, 7-i%8: 7, ptr[j]: 0xA5, &val: 0x80, |val = 0x04000, s0: 0x5000, s: 0x5000
i: 9, j: 1, 7-i%8: 6, ptr[j]: 0xA5, &val: 0x40, |val = 0x00000, s0: 0x5000, s: 0x5000
i: 10, j: 1, 7-i%8: 5, ptr[j]: 0xA5, &val: 0x20, |val = 0x00400, s0: 0x5000, s: 0x5400
i: 11, j: 1, 7-i%8: 4, ptr[j]: 0xA5, &val: 0x10, |val = 0x00000, s0: 0x5400, s: 0x5400
i: 12, j: 1, 7-i%8: 3, ptr[j]: 0xA5, &val: 0x08, |val = 0x00000, s0: 0x5400, s: 0x5400
i: 13, j: 1, 7-i%8: 2, ptr[j]: 0xA5, &val: 0x04, |val = 0x00010, s0: 0x5400, s: 0x5410
i: 14, j: 1, 7-i%8: 1, ptr[j]: 0xA5, &val: 0x02, |val = 0x00000, s0: 0x5410, s: 0x5410
i: 15, j: 1, 7-i%8: 0, ptr[j]: 0xA5, &val: 0x01, |val = 0x00001, s0: 0x5410, s: 0x5411
0x5411
21521
除s0
和s
中的值不是您想要的值,而忽略|val
之外,这些值是我们所期望的;基本的迭代结构受到控制。但是,|val
列显示存在问题 - 需要在输出格式中使用5个十六进制数字是意外的! i - 15
转换不会将位置放在您想要的位置,而是需要放置它们。
从这里开始,您需要自己解决问题。我希望这能为您提供有关如何调试此类问题的一些见解。
顺便提一下,问题已更新为:
s |= (ptr[j] & (1 << i%8)) << (15 - i); // Correction
在我的测试工具中,0x3CA5作为dat
中的初始值,产生输出:
0x00 0x00
0x3C 0xA5
i: 0, j: 0, 7-i%8: 7, ptr[j]: 0x3C, &val: 0x80, |val = 0x00000, s0: 0x0000, s: 0x0000
i: 1, j: 0, 7-i%8: 6, ptr[j]: 0x3C, &val: 0x40, |val = 0x00000, s0: 0x0000, s: 0x0000
i: 2, j: 0, 7-i%8: 5, ptr[j]: 0x3C, &val: 0x20, |val = 0x08000, s0: 0x0000, s: 0x8000
i: 3, j: 0, 7-i%8: 4, ptr[j]: 0x3C, &val: 0x10, |val = 0x08000, s0: 0x8000, s: 0x8000
i: 4, j: 0, 7-i%8: 3, ptr[j]: 0x3C, &val: 0x08, |val = 0x08000, s0: 0x8000, s: 0x8000
i: 5, j: 0, 7-i%8: 2, ptr[j]: 0x3C, &val: 0x04, |val = 0x08000, s0: 0x8000, s: 0x8000
i: 6, j: 0, 7-i%8: 1, ptr[j]: 0x3C, &val: 0x02, |val = 0x00000, s0: 0x8000, s: 0x8000
i: 7, j: 0, 7-i%8: 0, ptr[j]: 0x3C, &val: 0x01, |val = 0x00000, s0: 0x8000, s: 0x8000
i: 8, j: 1, 7-i%8: 7, ptr[j]: 0xA5, &val: 0x80, |val = 0x00080, s0: 0x8000, s: 0x8080
i: 9, j: 1, 7-i%8: 6, ptr[j]: 0xA5, &val: 0x40, |val = 0x00000, s0: 0x8080, s: 0x8080
i: 10, j: 1, 7-i%8: 5, ptr[j]: 0xA5, &val: 0x20, |val = 0x00080, s0: 0x8080, s: 0x8080
i: 11, j: 1, 7-i%8: 4, ptr[j]: 0xA5, &val: 0x10, |val = 0x00000, s0: 0x8080, s: 0x8080
i: 12, j: 1, 7-i%8: 3, ptr[j]: 0xA5, &val: 0x08, |val = 0x00000, s0: 0x8080, s: 0x8080
i: 13, j: 1, 7-i%8: 2, ptr[j]: 0xA5, &val: 0x04, |val = 0x00080, s0: 0x8080, s: 0x8080
i: 14, j: 1, 7-i%8: 1, ptr[j]: 0xA5, &val: 0x02, |val = 0x00000, s0: 0x8080, s: 0x8080
i: 15, j: 1, 7-i%8: 0, ptr[j]: 0xA5, &val: 0x01, |val = 0x00080, s0: 0x8080, s: 0x8080
0x8080
32896
这不是完整的答案。
我正在尝试将
dat
的值转换为s
。我需要它,因为我必须通过UDP套接字发送char数组。因此,在一端,我将整数存储为字符数组中的二进制,然后在另一端将其重新组合为整数。
您无需按位操作即可获得所需的结果;字节操作工作正常。
ptr[0] = dat >> 8;
ptr[1] = dat & 0xFF; // You could get away without the '& 0xFF'
// Transmit over UDP
dat = (ptr[0] << 8) | ptr[1];
使用unsigned char
(你正在做的)很重要;如果您使用普通char
(或更糟糕的是,signed char
),则必须担心符号位和符号扩展名。
作为对你进行位操作的练习,这有一些目的;值得你花一些时间来修复你的代码,以便它可以工作。作为一种操纵数据以便通过网络传输的方法,它不是一种好的工作方式,一旦你学会了有关位操作的内容,就应该抛弃它。
解决问题的一种方法 - 不一定是最好的,在任何方面 想象力,但一个有效的 - 是修复
lhs << (15 - i)
的LHS 移位,使其移位为0或1。例如:
((ptr[j] & (1 << (7 - i % 8))) ? 1 : 0) << (15 - i)