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 作为输出。我在这里做错了什么?
最佳答案
如所写,输出是不确定的,因为您从未设置 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
在我的测试工具中,dat
中以 0x3CA5 作为初始值,产生输出:
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
这不是完整的答案。
I am trying to get the value of
dat
intos
. I need it because I have to send the char array over a UDP socket. So at one end I will store integer as binary in a character array and then on the other end reassemble it as an integer.
您不需要进行按位运算即可获得您想要的结果;字节操作工作正常。
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。例如:block 引用>
((ptr[j] & (1 << (7 - i % 8))) ? 1 : 0) << (15 - i)
关于将 uint16_t 转换为十进制并将其按位存储在 char 数组中。检索 uint16_t 变量中的数据时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26943628/