C++ 位运算或vs加法

C++ 位运算或vs加法,c++,c,bitwise-operators,C++,C,Bitwise Operators,我正在从连接到树莓臂的传感器读取uint16。我通过以下方式将数据从little endian转换为big endian: // result = 0A 0B // 0B 00 | 00 0A (result << 8) | (result >> 8); 也许我已经回答了我自己的问题,但如果有人能评估一下,那就太好了。这不是我第一次自欺欺人。没有区别或优势,至少在现代处理器上没有。如果组合的位不重叠,换句话说,左侧的掩码对右侧设置的所有位都有零,反之亦然 此处显示的代码

我正在从连接到树莓臂的传感器读取uint16。我通过以下方式将数据从little endian转换为big endian:

// result = 0A 0B
// 0B 00 | 00 0A
(result << 8) | (result >> 8);

也许我已经回答了我自己的问题,但如果有人能评估一下,那就太好了。这不是我第一次自欺欺人。

没有区别或优势,至少在现代处理器上没有。如果组合的位不重叠,换句话说,左侧的掩码对右侧设置的所有位都有零,反之亦然

此处显示的代码:

// result = 0A0B0C0D 0E0F0A0B
// 0E0F0A0B 00000000 | 00000000 0A0B0C0D
((result << 8) & 0xFF00) | (result >> 8);
vs

当值已设置位7时

请注意,至少在叮当声中:

#include <cstdint>

uint32_t func1(uint32_t x)
{
    return (x >> 8) | ((x << 8) & 0xFF000000);
}

uint32_t func2(uint32_t x)
{
    return (x >> 8) + ((x << 8) & 0xFF000000);
}

没有区别或优势,至少在现代处理器上没有。如果被组合的位不重叠,换句话说,左侧的掩码对右侧设置的所有位都有零,反之亦然

此处显示的代码:

// result = 0A0B0C0D 0E0F0A0B
// 0E0F0A0B 00000000 | 00000000 0A0B0C0D
((result << 8) & 0xFF00) | (result >> 8);
vs

当值已设置位7时

请注意,至少在叮当声中:

#include <cstdint>

uint32_t func1(uint32_t x)
{
    return (x >> 8) | ((x << 8) & 0xFF000000);
}

uint32_t func2(uint32_t x)
{
    return (x >> 8) + ((x << 8) & 0xFF000000);
}
使用按位或|可以清楚地说明谁读代码的意图,这是很重要的一点

我会对这两种方法之间的速度差异感到惊讶

更好的办法是:

x = (x << 8) | (x >> 8);
因为传入位为零,所以不需要屏蔽左侧部分

在有符号整数的情况下,当对负值执行右移操作时会出现什么情况取决于实现,因此应使用可移植代码

x = (x << 8) | ((x >> 8) & 0xFF);
明确请求字节交换操作。

使用按位或|明确了谁读取代码的意图,这是重要的一点

我会对这两种方法之间的速度差异感到惊讶

更好的办法是:

x = (x << 8) | (x >> 8);
因为传入位为零,所以不需要屏蔽左侧部分

在有符号整数的情况下,当对负值执行右移操作时会出现什么情况取决于实现,因此应使用可移植代码

x = (x << 8) | ((x >> 8) & 0xFF);


明确要求进行字节交换操作。

您只是想了解其优点,还是想了解其区别?最后一部分似乎不是一个问题,主要是关于优势。我想我知道其中的区别,即使我不能明确解释。加法应该使用进位求和,而不是合并。一般来说,我会使用位运算符进行位运算,使用算术运算符进行算术运算,即使它们有时相等,而且现代芯片在执行周期方面相当有效。为什么需要用&0xFF00来屏蔽它?只有零位会拉屎。只做结果>8@Pynchia谢谢你指出。这是我几天前对自己感到疑惑的一件事,但我忘记了。它是从我的旧代码复制过来的,没有考虑它。你只是问它的优点,还是也问它的区别?最后一部分似乎不是一个问题,主要是关于优势。我想我知道其中的区别,即使我不能明确解释。加法应该使用进位求和,而不是合并。一般来说,我会使用位运算符进行位运算,使用算术运算符进行算术运算,即使它们有时相等,而且现代芯片在执行周期方面相当有效。为什么需要用&0xFF00来屏蔽它?只有零位会拉屎。只做结果>8@Pynchia谢谢你指出。这是我几天前对自己感到疑惑的一件事,但我忘记了。它是从我的旧代码复制而来的,没有考虑它。是的,你是对的。我目前正在使用一种32位的传感器。对不起。编辑它。但是我很不确定我是否理解你的例子。你如何|和+生成完全相同的代码?这些是不同的操作,通常会产生不同的结果:0x03+0x02=0x05,0x03 | 0x02=0x03@Mats彼得森:我现在明白你的例子了。还感谢您提供的汇编代码。这很有趣。@DrKoch:因为编译器意识到位不重叠,并且可以用leal指令生成比orl指令更好的代码,所以不要问我这里到底什么更好,这很可能是一个任意的选择,再多考虑一下,我认为知道这与ADD相同的主要优势在于,当结果用于索引到数组中时,编译器可能能够在寻址时做更多聪明的事情,例如arr[x>>8 | x是你的权利。我目前正在使用一个32位的传感器。抱歉。编辑了它。但我不确定我是否理解你的例子。你怎么做|和+生成完全相同的代码?这些是不同的操作,通常会产生不同的结果:0x03+0x02=0x05,0x03 | 0x02=0x03@Mats彼得森,我明白现在是您的示例。也感谢您提供的汇编代码。这非常有趣。@DrKoch:因为编译器意识到
它没有重叠,并且可以用leal指令生成比orl指令更好的代码不要问我这里到底什么更好,它很可能是一个任意的选择多考虑一下,我认为知道这与ADD相同的主要优势在于,当结果用于索引到数组中时,编译器可能能够在寻址时做更多聪明的事情,例如arr[x>>8|x请注意,x是uint16,而不是问题中的标准uint16。您的观察结果通常是有效的,但对于问题的上下文来说几乎肯定不是关键性的。请注意,x是uint16,而不是问题中的标准uint16。您的观察结果通常是有效的,但对于上下文来说几乎肯定不是关键性的问题的案文。
x = (x << 8) | ((x >> 8) & 0xFF);