[英]Bitwise shift unsigned long on Arduino
Why does the following not work on Arduino? 为什么以下内容在Arduino上不起作用?
unsigned long test = 1 << 20;
I've tested the bit shifting using the following sketch. 我已经使用以下草图测试了位移。
void setup() {
Serial.begin(9600);
unsigned long test = 0;
for(int i=0; i<32; i++)
{
test = 1 << i;
Serial.print("i:");
Serial.print(i);
Serial.print(" dec:");
Serial.println(test);
}
}
void loop() {
}
Which gives me the following output: 这给了我以下输出:
i:0 dec:1
i:1 dec:2
i:2 dec:4
i:3 dec:8
i:4 dec:16
i:5 dec:32
i:6 dec:64
i:7 dec:128
i:8 dec:256
i:9 dec:512
i:10 dec:1024
i:11 dec:2048
i:12 dec:4096
i:13 dec:8192
i:14 dec:16384
i:15 dec:4294934528 <--- ???
i:16 dec:0 <--- ???
i:17 dec:0 <--- ???
i:18 dec:0 <--- ???
i:19 dec:0 <--- ???
i:20 dec:0 <--- ???
i:21 dec:0 <--- ???
i:22 dec:0 <--- ???
i:23 dec:0 <--- ???
i:24 dec:0 <--- ???
i:25 dec:0 <--- ???
i:26 dec:0 <--- ???
i:27 dec:0 <--- ???
i:28 dec:0 <--- ???
i:29 dec:0 <--- ???
i:30 dec:0 <--- ???
i:31 dec:0 <--- ???
What happens at bit 15 and ongoing?? 第15位发生了什么并持续进行?
Testing the whole code in Xcode gives me the expected output. 在Xcode中测试整个代码会给我预期的输出。
int
seems to be only 16 bit wide on your target machine. int
在目标计算机上似乎只有16位宽。 1
is an int
, therefore shifting it by more than 15 bits invokes undefined behavour. 1
是一个int
,因此将其移位超过15位会调用未定义的行为。 The solution is simple, you should use a long
constant: 解决方法很简单,您应该使用
long
常量:
unsigned long test = 1UL << 20;
The language you write in is not exactly C, but this solution should still be correct. 您使用的语言并不完全是C,但是此解决方案仍应正确。
Incidentally, 1 << 40
invokes undefined behaviour if int
is 32 bits. 顺便说一句,如果
int
是32位,则1 << 40
调用未定义的行为。 Below is a simple test: 下面是一个简单的测试:
#include <stdio.h>
int a = 1, b = 40;
int main() {
printf("1 << 40 = %d\n", 1 << 40);
printf("1 << 40 = %d\n", 1 << 40);
printf("1 << 40 = %d\n", 1 << 40);
printf("%d << %d = %d\n", a, b, a << b);
}
On OS/X with clang
, I get this output: 在带有
clang
OS / X上,我得到以下输出:
~/dev/stackoverflow > make t42
clang -O3 -Wall -o t42 t42.c
t42.c:6:32: warning: shift count >= width of type [-Wshift-count-overflow]
printf("1 << 40 = %d\n", 1 << 40);
^ ~~
t42.c:7:32: warning: shift count >= width of type [-Wshift-count-overflow]
printf("1 << 40 = %d\n", 1 << 40);
^ ~~
t42.c:8:32: warning: shift count >= width of type [-Wshift-count-overflow]
printf("1 << 40 = %d\n", 1 << 40);
^ ~~
3 warnings generated.
~/dev/stackoverflow > ./t42
1 << 40 = 1386850896
1 << 40 = 256
1 << 40 = 512
1 << 40 = 256
~/dev/stackoverflow > ./t42
1 << 40 = 1477618256
1 << 40 = 256
1 << 40 = 512
1 << 40 = 256
clang
warns the programmer about the problem and insists on generating undefined behaviour, with consistently inconsistent output. clang
向程序员警告该问题,并坚持生成不确定的行为,输出始终不一致。 Amazing isn't it? 是不是很神奇? A good example of why one should never ignore compiler warnings
为什么不应该忽略编译器警告的一个很好的例子
You are shifting 1
which is a 16-bit int
. 您正在将
1
转换为16位int
。 This works up to 16384
but 32768
is -32768
or 0x8000
which is then sign-extended when assigned to unsigned long
as 0xFFFF8000
, which is 4294934528
. 这对于高至
16384
,但32768
是-32768
或0x8000
时,分配给它,然后符号扩展unsigned long
为0xFFFF8000
,这是4294934528
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.