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

sau*_*wal 8 c bit-manipulation

我有一个包含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);
}
Run Code Online (Sandbox Code Playgroud)

结果:

0xABCD 0xCD
Run Code Online (Sandbox Code Playgroud)

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

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

Sam*_*ack 5

你可以这样做:

uint16_t val = 0xABCD;
uint8_t vr = val & 0x00FF;    // Bitwise AND Operation
Run Code Online (Sandbox Code Playgroud)

使用此按位操作,您将获得8位 LSB

  • @Amol:事实并非如此.对于无符号类型,如OP所使用的,行为由标准指定. (4认同)
  • 从性能(内存和速度)的角度来看,它与"vr = val"有什么不同? (3认同)
  • 你也可以做 `vr = (uint8_t)val`(这正是 OP 正在做的,除了缺少显式转换(在最坏的情况下会产生编译警告,但在任何一种情况下都不会产生任何运行时影响))。 (2认同)

小智 5

虽然两个答案都是正确的,但这里的位屏蔽是完全冗余的.它在转换为时会隐式发生uint8_t.如果没有确切大小的整数类型(并且,考虑到性能,您应该考虑这一点,因为在使用机器的本机字大小时性能通常最佳),这将是不同的:

unsigned int val = 0xabcd;
unsigned int vr = val & 0xff;
assert(vr == 0xcd);
Run Code Online (Sandbox Code Playgroud)

但是当你真的需要这些确切大小的类型时,最好的代码是恕我直言

uint16_t val = 0xabcd;
uint8_t vr = (uint8_t) val;
Run Code Online (Sandbox Code Playgroud)

明确的演员在这里记录意图!没有它,一个好的编译器会警告你可能会丢失信息的隐式转换(并且你应该总是启用编译器警告,例如gcc -Wall -Wextra -pedantic,以捕获你偶然进行这种转换的情况).

使用精确大小的类型的所有变体的性能应该是相同的,因为一个体面的编译器将为所有变体发出相同的代码.使用just的版本unsigned int 可能会更好一点.

[编辑]:正如您所询问的内存性能一样:您不太可能通过使用获得某些东西,uint8_t因为某些体系结构需要将小于本机字大小的值与字边界对齐.如果他们不需要它,那么将它们对齐可能仍然会更快,因此编译器可能会决定这样做.这只是引入了未使用的填充字节.使用gcc,您可以使用该选项-Os来优化大小,并且由于x86体系结构是字节可寻址的,这可能导致在uint8_tPC上没有填充的情况下使用,但因此速度较低.大多数情况下,速度与内存是一种权衡,你可以有一个或另一个.