эффективный способ преобразования 16-битного значения в 8-битное

у меня есть переменная, которая содержит 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

Я хочу знать, это хороший способ взять 8 LSB из 16-битной переменной?

EDIT:
Пожалуйста, добавьте проблемы с производительностью (с точки зрения памяти и скорости) с этим конкретным способом реализации.

3 ответов


хотя оба ответа верны, битовая маскировка здесь полностью избыточна. Это происходит неявно при преобразовании в uint8_t. Без точно определенных типов целых чисел (и, говоря о производительности, вы должны учитывать это, потому что производительность в целом лучше всего при использовании собственного размера слова машины), это будет отличаться:

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

но когда вам действительно нужно иметь именно этот тип размера, лучший код-IMHO

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

явный cast здесь, чтобы документировать намерение! Без него хороший компилятор предупредит вас о неявном преобразовании, возможно, потеряв информацию (и вы всегда должны включать предупреждения компилятора, например, для gcc -Wall -Wextra -pedantic, чтобы поймать случаи, когда вы делаете такое преобразование случайно).

производительность всех вариантов с использованием размер типы должны быть одинаковыми, потому что приличный компилятор будет выдавать один и тот же код для всех из них. Версия, используя только unsigned int может выполнить немного лучше.

[edit]: как вы спрашиваете о производительность памяти, тоже: маловероятно, что вы получите что-то с помощью uint8_t потому что некоторые архитектуры требуют, чтобы значения меньше размера собственного слова были выровнены по границам слов. Если они этого не требуют, их выравнивание может быть быстрее, поэтому компилятор может решить это сделать. Это просто вводит неиспользуемые байты заполнения. С GCC, вы можете используйте опцию -Os оптимизировать для размера и as x86 архитектура байт-адресуемой, это может привести к uint8_t используется без заполнения на ПК, но, следовательно, с меньшей скоростью. В большинстве случаев скорость против памяти-это компромисс, вы можете иметь либо то, либо другое.


Вы можете сделать как ниже:

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-битное целое число несет только 8-битные фунты из 16-битного значения и отбрасывает оставшиеся 8-битные MSB (по умолчанию, когда присваивается большее значение).