按位NOT和比较的无符号与已签名问题

时间:2013-06-28 04:11:18

标签: arduino

经过一些头疼,我已经确定签名和未签名的字符在==符号时有惊人的差异。

void loop()
{
}

void setup()
{
  unsigned char ucA = 0x55;
  unsigned char ucB = 0xAA;
  unsigned char ucB_not;

  char cA = 0x55;
  char cB = 0xAA;

  Serial.begin( 115200);

  if ( ucA == ~ucB)
    Serial.println( "unsigned -- match");
  else
    Serial.println( "unsigned -- no match");


  if ( cA == ~cB)
    Serial.println( "signed -- match");
  else
    Serial.println( "signed -- no match");

  ucB_not = ~ucB;
  if ( ucA == ucB_not)
    Serial.println( "unsigned, seperate variable -- match");
  else
    Serial.println( "unsigned, seperate variable -- no match");

}

我得到的输出是:

unsigned -- no match
signed -- match
unsigned, seperate variable -- match

在比较之前是否有一些规则值会变宽?即使如此,无符号情况应该不是问题,是吗?

我添加了最后一个案例 - 创建一个单独的变量似乎没有问题。

我正在使用Arduino版本1.0.5。

1 个答案:

答案 0 :(得分:2)

在C和C ++中,整数类型比int更窄的运算符的操作数得到promoted to an int。如果较小的类型是签名的,那么提升的类型是符号扩展的 - 签名的char值-x被提升为具有相同值-x的signed int,这在2的补码机器中意味着为它添加前缀0xff个字节。如果将操作的结果分配回较小的类型,则会将其截断。

您的三个案例适用以下规则:

  1. 将unsigned char 0xaa提升为unsigned int 0x00aa,将unsigned char 0x55提升为unsigned int 0x0055。倒置0x00aa会导致0xff55不等于0x0055

  2. 签名字符0xaa被提升为已签名的int 0xffaa(带负签名的值已签名扩展 - 已签名的字符值-86将提升为已签名的int值-86 )并签名char 0x55到签名int 0x0055(正签名char值+85被提升为signed int value +85)。倒置0xffaa会使0x0055等于0x0055

  3. 无符号字符0xaa被提升为unsigned int 0x00aa,反转为0xff55,然后存储为unsigned char,导致它被截断为0x55。稍后将unsigned char 0x55与unsigned char 0x55进行比较,发现它们相等。