简体   繁体   English

在Arduino上按位移位无符号长

[英]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-327680x8000时,分配给它,然后符号扩展unsigned long0xFFFF8000 ,这是4294934528

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM