我已经用高级动态类型语言编写了很长时间,但我刚刚开始使用C ++(在Arduinos上)。我正在尝试编写一个函数,将int
和0
之间的3个0xFF
(RGB颜色值)转换为单个unsigned long
,最多可达{{1} }}。无符号长整数可以达到0xFFFFFF
,因此应该有效。
我在我的个人计算机上编写了以下测试,并使用0xFFFFFFFF
编译了它:
g++
正如预期的那样输出:
#include <iostream>
using namespace std;
int main(){
unsigned long red = 0xff * 0x10000;
unsigned long green = 0xff * 0x100;
unsigned long blue = 0xff;
unsigned long color = red + green + blue;
cout << hex << red << "\n";
cout << hex << green << "\n";
cout << hex << blue << "\n";
cout << hex << color << "\n";
}
这是有道理的。但是,我尝试在我的Arduino上运行以下命令:
ff0000
ff00
ff
ffffff
除非我遗漏了某些内容(完全可能),否则此代码在功能上是相同的,除非它使用不同的方法来编写其输出。但是,这就是打印出来的内容:
void setup(){
unsigned long red = 0xff * 0x10000;
unsigned long green = 0xff * 0x100;
unsigned long blue = 0xff;
unsigned long color = red + green + blue;
Serial.begin(9600);
Serial.println(String(red, HEX));
Serial.println(String(green, HEX));
Serial.println(String(blue, HEX));
Serial.println(String(color, HEX));
}
void loop(){}
怀疑架构可能与它有关,我尝试在Mega 2560和Rainbowduino 3.0(基本上是一个Duemilanove w / ATmega 328)上运行该代码,两者都有相同的结果。如果我使用不同的数据类型,例如ff0000
ffffff00
ff
feffff
。
我真的不知道发生了什么。有人可以提供解释吗?
答案 0 :(得分:2)
在C ++中,常量表达式在编译时计算。看起来arduino的编译器已经错误地执行了计算 - 它将0xFF
视为否定,并对其进行了符号扩展;这就是为什么顶部字节设置为0xFF
。
您可以使用type-specific suffixes强制常量使用正确的类型,如下所示:
unsigned long red = 0xffUL * 0x10000UL;
unsigned long green = 0xffUL * 0x100UL;
unsigned long blue = 0xffUL;
unsigned long color = red + green + blue;
UL
后缀代表unsigned long
。
不是将数字乘以2的幂并将结果相加,您可以使用shift和按位OR,如下所示:
unsigned long red = 0xffUL;
unsigned long green = 0xffUL;
unsigned long blue = 0xffUL;
unsigned long color = (red << 16)
| (green << 8)
| (blue << 0);
上面的零位移是完全没必要的 - 编译器会优化它。我添加了它以获得更一致的外观。