我想将两个字节组合成一个无符号长变量,我当前的代码不起作用。我使用的是MPLAB C18编译器,这是我的代码。
unsigned long red = 0;
BYTE t[2];
t[0] = 0x12;
t[1] = 0x33;
red = 100 * t[0] + t[1];
printf("%lu", red);
请让我知道为什么我没有得到1233作为我的输出。
答案 0 :(得分:5)
当您将t[0]
乘以100
后,您将256
乘以t[0]
。更好的方法是将t[1]
向左移8位并添加red = ( t[0] << 8 ) | t[1];
。
{{1}}
答案 1 :(得分:1)
您会注意到数组中的值是使用0x
前缀指定的。 100
不等于0x100
。
您的编译器不合规。此外,二元运算符对有符号整数类型的定义很差,BYTE
可能是这些类型。以下是我编写代码的方法,为安全起见:
unsigned long red = 0;
BYTE t[2];
t[0] = 0x12;
t[1] = 0x33;
red = (unsigned char) t[0];
red = red * 0x100;
red = red + (unsigned char) t[1];
printf("Decimal: %lu\n"
"Hexadecimal: 0x%lx\n", red, red);
答案 2 :(得分:0)
首先请注意,MPLAB C18与C标准存在一些差异。阅读user manual,特别是标有“ISO分歧”的第2.7节。
因此,请注意C18执行字符串促销而不是整数促销,也适用于文字。因此,如果将0x80和0x80一起添加,则得到0x00。如果需要更大的常量,避免这种情况的方法与正常工作的方法相同使用“L”或“UL”后缀强制计算32位,也可以在需要时进行转换。
编译器的优化器可能有点不完善,您需要检查反汇编。如果使用32位字符,它可能会发出32位代码,即使只需要8位也是如此。您可以通过转换计算结果来解决此问题,例如:
#define C8BIT ((unsigned char)(((0x12UL * 0x100UL) + 0xC0UL)>>6))
(只是一个任意计算的示例,否则会溢出)
在您发布的示例中,问题类似,您基本上使用无符号字符,编译器提升为unsigned char,除了它以至少16位深度计算。对于有问题的线路,一个适当而干净的解决方案可能是:
red = (0x100UL * (unsigned long)(t[0])) + ((unsigned long)(t[1]));
如果性能很重要(假设t [0]和t [1]只有一些示例值,那么可能在实际程序中得到任意内容)你可能想要检查反汇编并最终求助于此:
red = (0x100U * t[0]) + t[1];
或
red = (((unsigned short)(t[0]))<<8) + t[1];
理智的编译器(甚至包括C18)应该在这些上给出正确的结果。我还展示了一个带有移位的版本,因为C18在优化时不太强大,并且可能包含对那里的多次例程的库调用。我省略了转换t [0]和t [1],因为编译器应该正确地推广它们(0x100U要求至少16位促销),并且演员可能会混淆编译器添加额外的16位逻辑(C18在这个术语中非常弱! )使用文字'0'操作数。如果性能很重要,请检查拆卸,否则只需使用干净的解决方案!
您可能还想检查BYTE类型。它应该是unsigned char,但不一定。您可能希望定义具有固定大小的类型(例如typedef unsigned char uint8;
等)以便一致使用。