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

时间:2015-07-24 05:37:55

标签: 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);
}

结果:

0xABCD 0xCD

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

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

4 个答案:

答案 0 :(得分:5)

您可以执行以下操作:

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

使用此按位运算,您将获得8位LSB

答案 1 :(得分:5)

虽然两个答案都是正确的,但这里的位屏蔽是完全冗余的。它在转换为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 的版本可能执行得更好。

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

答案 2 :(得分:2)

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

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

或者这也可以通过简单的类型转换来完成,因为8位整数仅携带来自16位值的LBS 8位,&amp;丢弃剩余的MSB 8位(默认情况下,当分配更大的值时)。

答案 3 :(得分:0)

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

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