c - Arduino 上的按位移位 unsigned long

标签 c arduino bit-manipulation long-integer bit-shift

为什么以下内容不适用于 Arduino?

unsigned long test = 1 << 20;

我已经使用以下草图测试了移位。

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() {

}

这给了我以下输出:

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            <--- ???

第 15 位和持续发生了什么?

在 Xcode 中测试整个代码给了我预期的输出。

最佳答案

int在您的目标机器上似乎只有 16 位宽。 1是一个 int ,因此将其移动超过 15 位会调用未定义的行为。解决方案很简单,您应该使用 long常量:

 unsigned long test = 1UL << 20;

您编写的语言不完全是 C,但这个解决方案应该仍然是正确的。

顺便说一句,1 << 40如果 int 则调用未定义的行为是 32 位。下面是一个简单的测试:

#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);
}

在 OS/X 上 clang ,我得到这个输出:

~/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警告程序员有关问题并坚持生成未定义的行为,输出始终不一致。是不是很神奇?一个很好的例子,说明为什么永远不要忽略编译器警告

关于c - Arduino 上的按位移位 unsigned long,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29460115/

相关文章:

c++ - 如何将 4 个 2 位值合并为 1 个 8 位值?

c - 在十六进制数组中写入位

c - 如何检查数组中的特定值

使用 JNI 将 C 数组复制到 Java 数组

c - 显示星号与使用函数显示字符

c++ - 使用比例计算值

c - 在 C 中使用链表实现 Eratosthenes 筛法(Segmentation Fault 错误)

c - 为什么这个 If 语句不执行代码?

arduino - VS Code给出Arduino的标题错误?缺少官方 header ?

c++ - 我不明白这个 C++ 语法