我试图在Arduino中实现逻辑右移(即避免符号扩展),并且在阅读了Arduino BitShift指南(https://www.arduino.cc/en/Reference/Bitshift)之后,它建议将无符号变量向右移,不会导致符号扩展:
当您将x向右移位y位(x>> y)时,x中的最高位为 a 1,行为取决于x的确切数据类型。如果x是类型 int,最高位是符号位,确定x是否为 是否消极,正如我们上面所讨论的那样。在那种情况下,标志 由于历史原因,比特被复制到较低位:
int x = -16; // binary: 1111111111110000 int y = x >> 3; // binary: 1111111111111110 This behavior, called sign extension, is often not the behavior you want. Instead, you may
希望零从左侧移入。事实证明是正确的 unsigned int表达式的shift规则是不同的,所以你可以使用 一个类型转换来压制从左边复制的那些。
在我的测试中,它没有那样工作:
Serial.print( ((uint32_t)(1<<15)) >> 15, BIN);
打印:
11111111111111111
这意味着,正在进行标志扩展。 我也从那里尝试了建议的例子,结果相同。
我做错了吗? 是否可以进行移位并强制操作是逻辑而不是算术?
答案 0 :(得分:4)
首先,我认为您遗漏了一些关键信息:看起来您必须使用具有16位/* Write a program that asks the user
* to enter the starting point and end
* point of the counting range and the
* increment value and displays the total
* of the numbers within that range
*/
int start;
int end;
int increment;
int sum = 0;
int count= 0;
Console.WriteLine(" Enter the start number ");
start = Int32.Parse(Console.ReadLine());
Console.WriteLine(" Enter the end number ");
end = Int32.Parse(Console.ReadLine());
Console.WriteLine(" Enter the increment number ");
increment = Int32.Parse(Console.ReadLine());
for ( start = ; end <= start ; count = count + increment )
{
Console.WriteLine(" Number is: " + count);
}
Console.WriteLine(" Sum is: " + sum);
Console.ReadKey();
类型的Arduino板(例如,Arduino Uno)。
这里的问题是整数提升在C和C ++中的工作原理。将16位有符号整数文字int
转换为32位无符号整数文字时,将执行以下步骤:
我没有坐16位机器来测试它,但我可以使用此测试程序在我的64位笔记本电脑上复制相同的行为:
1<<15
所以你可以在这个程序中看到,它不是执行不需要的符号扩展的#include <stdio.h>
#include <inttypes.h>
int main(int argc, const char* argv[]) {
printf("%" PRIx64 "\n", ((uint64_t)(1 << 31)));
// prints ffffffff80000000
printf("%" PRIx64 "\n", ((uint64_t)(1 << 31)) >> 31);
// prints 1ffffffff
return 0;
}
操作,而是从32位有符号整数转换为64-位无符号整数,因为强制转换实际上是这样的:
>>
→int32_t
→int64_t
如果你想避免额外的符号扩展,你应该以无符号文字开头(正如一些程序员在他的评论中建议的那样),或者使用相同宽度的无符号类型进行转换。其中任何一个都应该有效:
uint64_t