2015-10-04 9 views
1

У меня есть 32-битный int, и я хочу установить первые 10 бит на конкретный номер.Установите первые 10 бит int

IE

32-разрядное ИНТ:

11101010101010110101100100010010 

Я хочу, чтобы первый 10 бит быть номером 123, который является

0001111011 

Так что результат будет

00011110111010110101100100010010 

Кто-нибудь знает Насколько я мог бы это сделать? Я знаю, что нам нужно делать бит-сдвиги, но я не очень хорош, поэтому я не уверен, что

Спасибо!

+0

Что вы имеете в виду под «первым битам»? Самый значительный или наименее значимый? – EOF

+1

'unsigned shift = (32-10); unsigned long mask = (1ul << shift) -1; y = (x & mask) | (123 * 1ul << shift); ' – chux

+0

@chux: почему это не ответ? –

ответ

2
uint32_t result = (input & 0x3fffff) | (newval << 22); 

0x3fffff маска из самых высоких 10 бит (он имеет самый низкий 22 бит набора). Вы должны перенести новое значение на самые высокие 10 бит на 22 места.

+0

Использование 'uint32_t' является хорошим, так как оно не предполагает ширину' int/unsigned'. Однако код предполагает, что 'newval' - 32 + бит. – chux

+1

Небольшое предложение: использование 'U' в константах делает их более понятными для неподписанных (даже лучше:' UINT32_C'. В зависимости от ввода, конечно, но что, если 'input' является' # define'? (Лучше вы добавляете объявления для них тоже). – Olaf

+0

Я просто попытался показать концепцию. Может быть, немного ленив, этот ответ. Но тогда вы тоже могли бы задать вопрос;) –

0

Вы можете «стереть» биты (установить их в 0), используя бит мудрый и («&»); бит, равный 0 в любом значении, будет равен 0.

Вы можете установить бит в 1, используя бит мудрый или ('|'); бит, равный 1 в любом значении, будет равен 1.

Итак: и ваш номер со значением, где первые 10 бит равны 0, а остальные - 1; затем 'или' он с первыми 10 бит, которые вы хотите ввести, и 0 для других бит. Если вам нужно вычислить это значение, то левым сменом будет путь.

1
  1. Преобразовать входы беззнаковых 32-битных целых числа

    uint32_t num = strtoul("11101010101010110101100100010010", 0, 2); 
    uint32_t firstbits = 123; 
    
  2. Маскирования нижних бит 32-10. Создание маски путем сдвига unsigned long 1 22 мест осталось сделать 100_0000_0000_0000_0000_0000 затем декремента к 11_1111_1111_1111_1111_1111

    uint32_t mask = (1UL << (32-10)) - 1; 
    num &= mask; 
    
  3. Или в firstbits сдвинутый влево на 32-10

    num |= firstbits << (32-10); 
    
  4. Или в 1 строке:

    (num & (1UL << (32-10)) - 1) | (firstbits*1UL << (32-10)) 
    

Подробно о firstbits*1UL. Тип firstbits не определяется OP и может быть только 16-разрядным int. Чтобы гарантировать, что код может сдвинуться и сформировать ответ, который превышает 16 бит (минимальная ширина int), несколько на 1UL, чтобы гарантировать, что значение не имеет знака и имеет ширину не менее 32 бит.

+0

Что заставляет вас думать, что ввод представляет собой строку? –

+0

@ScottHunter вопрос сказал: «У меня 32-битный int», он не указал, как этот int был получен. Это также не имеет отношения к вопросу; вопрос о том, что мы делаем, когда у нас есть int ('num' в этом ответе). –

+0

@ M.M: Именно поэтому я поставил под сомнение наличие преобразования строк в этом ответе. –

0

Как насчет использования битовых полей в C в сочетании с объединением? Следующая структура позволяет вам установить все 32-битное значение, верхние 10 бит или нижние 22 бита. Это не так универсально, как общая функция, но вы не можете легко ошибиться при ее использовании.Имейте это в виду, и большинство решений могут не работать на всех целых размерах и следить за его точностью.

union uu { 
    struct { 
     uint32_t bottom22 : 22; 
     uint32_t top10 : 10; 
    } bits; 
    uint32_t value; 
}; 

Вот пример использования:

int main(void) { 
    union uu myuu; 
    myuu.value = 999999999; 
    printf("value = 0x%08x\n", myuu.value); 

    myuu.bits.top10 = 0; 
    printf("value = 0x%08x\n", myuu.value); 

    myuu.bits.top10 = 0xfff; 
    printf("value = 0x%08x\n", myuu.value); 

    return 0; 
} 

Выход:

value = 0x3b9ac9ff 
value = 0x001ac9ff 
value = 0xffdac9ff 
+0

«нелегко совершить ошибку» -> 1) Бит-поля целочисленного типа шире, чем 'int/unsigned', не переносимы. 'int/unsigned' должен быть только 16 бит. - распространенный во встроенном процессоре в 2015 году. 2) Порядок «bottom22/top10» зависит от конца. Этот код может установить нижний 10 вместо этого. OTOH будет иметь соответствующую квалификацию, это хороший подход. – chux

0

Вы также можете взять маску и заменить подход, при котором вы обнулить младшие биты требуется удержать 123, а затем просто | (ИЛИ) значение с 123 для получения конечного результата. Вы можете выполнить ту же самую вещь с сдвигами, как показано несколькими другими ответами, или вы можете сделать это с помощью масок:

#include <stdio.h> 

#ifndef BITS_PER_LONG 
#define BITS_PER_LONG 64 
#endif 

#ifndef CHAR_BIT 
#define CHAR_BIT 8 
#endif 

char *binpad2 (unsigned long n, size_t sz); 

int main (void) { 


    unsigned x = 0b11101010101010110101100100010010; 
    unsigned mask = 0xffffff00; /* mask to zero lower 8 bits */ 
    unsigned y = 123;   /* value to replace zero bits */ 

    unsigned masked = x & mask; /* zero the lower bits  */ 

    /* show intermediate results */ 
    printf ("\n x  : %s\n", binpad2 (x, sizeof x * CHAR_BIT)); 
    printf ("\n & mask : %s\n", binpad2 (mask, sizeof mask * CHAR_BIT)); 
    printf ("\n masked : %s\n", binpad2 (masked, sizeof masked * CHAR_BIT)); 
    printf ("\n | 123 : %s\n", binpad2 (y, sizeof y * CHAR_BIT)); 

    masked |= y; /* apply the final or with 123 */ 

    printf ("\n final : %s\n", binpad2 (masked, sizeof masked * CHAR_BIT)); 


    return 0; 
} 

/** returns pointer to binary representation of 'n' zero padded to 'sz'. 
* returns pointer to string contianing binary representation of 
* unsigned 64-bit (or less) value zero padded to 'sz' digits. 
*/ 
char *binpad2 (unsigned long n, size_t sz) 
{ 
    static char s[BITS_PER_LONG + 1] = {0}; 
    char *p = s + BITS_PER_LONG; 
    register size_t i; 

    for (i = 0; i < sz; i++) 
     *--p = (n>>i & 1) ? '1' : '0'; 

    return p; 
} 

Выход

$ ./bin/bitsset 

x  : 11101010101010110101100100010010 

& mask : 11111111111111111111111100000000 

masked : 11101010101010110101100100000000 

| 123 : 00000000000000000000000001111011 

final : 11101010101010110101100101111011 
Смежные вопросы