手动转换签名的char

时间:2011-09-25 14:14:09

标签: c dynamic-c

我正在使用一些嵌入式硬件,一个使用Dynamic C 9的Rabbit SBC。

我正在使用微控制器使用其中一个串行端口从数字罗盘传感器读取信息。

传感器使用单个带符号字节将值发送到微控制器。 (-85到85)

当我收到这些数据时,我将其放入char变量

这对正值很好,但是当传感器开始发送负值时,读数会跳到255,然后再回到0.我认为这是因为最后一位用于确定负值/积极的,正在扭曲真正的价值观。

我的初衷是将我的数据类型更改为signed char

但是,我遇到的问题是我使用的微控制器上的Dynamic C版本本身不支持带符号的char值,只有unsigned。

我想知道是否有办法将我收到的数据手动转换为有符号值?

4 个答案:

答案 0 :(得分:11)

您只需要提取参考书并阅读控制器如何表示负数。其余的只是打字。

例如,两个补码通过取值mod 256表示,因此您只需要通过模数进行调整。

int signed_from_unsignedchar(unsigned char c)
{
    int result = c;
    if (result >= 128) result -= 256;
    return result;
}

One's complement要简单得多:你只需翻转一下。

int signed_from_unsignedchar(unsigned char c)
{
    int result = c;
    if (result >= 128) result = -(int)(unsigned char)~c;
    return result;
}

符号幅度通过设置高位表示负数,因此您只需要清除该位并否定:

int signed_from_unsignedchar(unsigned char c)
{
    int result = c;
    if (result >= 128) result = -(result & 0x7F);
    return result;
}

答案 1 :(得分:1)

我认为这就是你所追求的(假定一个32位的int和一个8位的char):

unsigned char c = 255;
int i = ((int)(((unsigned int)c) << 24)) >> 24;

当然我假设您的平台支持有符号整数,但情况可能并非如此。

答案 2 :(得分:1)

有符号和无符号值都只是一堆位,它是你的解释,使它们签名或无符号。例如,如果您的硬件产生2的补码,如果您读取0xff,您可以将其解释为-1或255,但它们实际上是相同的数字。

现在,如果您只有unsigned char,则必须使用它来模拟负值的行为。

例如:

c < 0

更改为

c > 127

幸运的是,添加不需要改变。减法也是一样的(检查一下,我不是100%肯定)。

例如,对于乘法,您需要自己检查。首先,在2的补码中,这是你如何获得数字的正值:

pos_c = ~neg_c + 1

从数学上讲256-neg_c全等模256只是-neg_c

现在假设您要将两个未签名的数字相乘,但您希望将它们解释为已签名。

unsigned char abs_a = a, abs_b = b;
char final_sign = 0; // 0 for positive, 1 for negative
if (a > 128)
{
    abs_a = ~a+1
    final_sign = 1-final_sign;
}
if (b > 128)
{
    abs_b = ~b+1
    final_sign = 1-final_sign;
}
result = abs_a*abs_b;
if (sign == 1)
    result = ~result+1;

你明白了!

答案 3 :(得分:0)

如果您的平台支持signed int,请查看其他一些答案。

如果没有,并且值肯定在-85和+85之间,并且它是二进制补码,则将85添加到输入值并计算出程序逻辑以解释0到170之间的值,这样您就不必再搞乱签名整数。

如果这是一个补充,请尝试:

if (x >= 128) {
    x = 85 - (x ^ 0xff);
} else {
    x = x + 85;
}

这将为您留下0到170之间的值。

编辑:是的,还有符号幅度。然后在此处使用相同的代码,但将第二行更改为x = 85 - (x & 0x7f)

相关问题