如何将两个Bytes数组转换为unsigned long变量?

时间:2013-06-11 19:26:26

标签: c microcontroller pic mplab

我想将两个字节组合成一个无符号长变量,我当前的代码不起作用。我使用的是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作为我的输出。

3 个答案:

答案 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;等)以便一致使用。