将 16 位值转换为 8 位值的有效方法

efficient way to convert 16 bit value to 8 bit value

我有一个包含 16 位值的变量。我只需要 8 LSB。其余 8 位需要丢弃。

我正在使用此代码来执行此操作。

#include<stdio.h>
#include<stdint.h>
int main(int argc, char *argv[])
{
    int linkIndx,size=128;

    uint16_t val = 0xABCD;
    uint8_t vr;

    vr = val; //this assignment discards upper 8-bits 

    printf("0x%X 0x%X ", val, vr);
}

结果:

0xABCD 0xCD

我想知道,从 16 位变量中取出 8 LSB 是一种好方法吗?

编辑:
请使用这种特定的实现方式添加性能问题(从内存和速度的角度来看)。

您可以进行以下操作:

uint16_t val = 0xABCD;
uint8_t vr = val & 0x00FF;    // Bitwise AND Operation

使用这个按位运算你会得到 8 位 LSB

您可以使用位掩码概念。
像这样,

uint16_t val = 0xABCD;
uint8_t vr  = (uint8_t) (val & 0x00FF);

或者这也可以通过简单的显式类型转换来完成,因为 8 位整数仅携带 16 位值中的 LBS 8 位,并丢弃剩余的 MSB 8 位(默认情况下,当分配一个较大的值)。

虽然两个答案都是正确的,但这里的位掩码是完全多余的。它在转换为 uint8_t 时隐式发生。如果没有精确大小的整数类型(而且,说到性能,您应该考虑这一点,因为使用机器的本机字大时通常性能最好),这将有所不同:

unsigned int val = 0xabcd;
unsigned int vr = val & 0xff;
assert(vr == 0xcd);

但是当你真的需要这些精确大小的字体时,最好的代码是恕我直言

uint16_t val = 0xabcd;
uint8_t vr = (uint8_t) val;

显式转换是为了记录意图!没有它,一个好的编译器会警告您隐式转换可能会丢失信息(并且您应该始终启用编译器警告,例如 gcc -Wall -Wextra -pedantic,以捕获意外进行此类转换的情况 ).

使用大小完全相同的类型的所有变体的性能应该是相同的,因为一个体面的编译器会为所有这些变体发出相同的代码。仅使用 unsigned int 的版本可能 表现更好一些。

[编辑]:正如您询问 内存性能 一样:您不太可能通过使用 uint8_t 因为某些体系结构需要小于本机字大小的值才能与字边界对齐。如果他们不需要它,让它们对齐可能仍然更快,因此编译器可能会决定这样做。这只是引入了未使用的填充字节。使用 gcc,您可以使用选项 -Os 来优化大小,并且由于 x86 体系结构是字节可寻址的,这可能导致 uint8_t 在 PC 上使用时没有填充,但因此较低的速度。大多数时候,速度与内存是一种权衡,你可以选择其中之一。

虽然上面的答案是正确的,但这里有另一种方法。此方法不需要按位运算

#include <stdint.h>
#include <stdio.h>

union converted16{
        struct{
                uint8_t lsb;
                uint8_t msb;
        }raw;
        uint16_t data;

}mynumber;

int main(int argc, char *argv[]){

        mynumber.data = 0xFEAB;
        printf("msb = %u, lsb = %u\n",mynumber.raw.msb, mynumber.raw.lsb);
        return 1;
}