经过一些头疼,我已经确定签名和未签名的字符在==符号时有惊人的差异。
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。
答案 0 :(得分:2)
在C和C ++中,整数类型比int更窄的运算符的操作数得到promoted to an int。如果较小的类型是签名的,那么提升的类型是符号扩展的 - 签名的char值-x
被提升为具有相同值-x
的signed int,这在2的补码机器中意味着为它添加前缀0xff
个字节。如果将操作的结果分配回较小的类型,则会将其截断。
您的三个案例适用以下规则:
将unsigned char 0xaa
提升为unsigned int 0x00aa
,将unsigned char 0x55
提升为unsigned int 0x0055
。倒置0x00aa
会导致0xff55
不等于0x0055
。
签名字符0xaa
被提升为已签名的int 0xffaa
(带负签名的值已签名扩展 - 已签名的字符值-86
将提升为已签名的int值-86
)并签名char 0x55
到签名int 0x0055
(正签名char值+85
被提升为signed int value +85
)。倒置0xffaa
会使0x0055
等于0x0055
。
无符号字符0xaa
被提升为unsigned int 0x00aa
,反转为0xff55
,然后存储为unsigned char,导致它被截断为0x55
。稍后将unsigned char 0x55
与unsigned char 0x55
进行比较,发现它们相等。