2013-07-20 3 views
3

Пусть мой проект включает в себя заголовок из 3-сторонней библиотеки, которая содержит следующее:Как вычислить максимальное поддерживаемое значение подписанного битового поля?

struct foo { 
    signed int x:4; 
}; 

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

+0

надежно можно хранить только '1111'. –

+1

@GrijeshChauhan: «Не предполагая, что бит-поле всегда будет иметь ширину 4.» Сторонний разработчик может изменить ширину на 5 в следующей версии. Или 13. Или что-то еще. Я не хочу, чтобы мой код прерывался при изменении ширины битового поля. –

+0

Я не получил :(, * 'Не предполагая, что бит-поле всегда будет иметь ширину 4' *, у него всегда будет 4-бит с любым компилятором ... я что-то упустил? –

ответ

1

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

Для битполов реализация не может предоставить эти значения, поэтому вы застряли.

Это одна из причин, по которой биттоны действительно не должны быть signed. Битвые поля предназначены для манипуляций с битами и ничего больше, бит знака тогда просто теряется.

Если ваше поле будет unsigned, все будет легко. Вам просто нужно сохранить -1, и вы получите значение со всеми, максимальное значение для «type».

5

Поскольку размер битового поля не может быть вычислены с sizeof, это может помочь:

#include <stdio.h> 

struct foo { 
    signed int x: 4; 
}; 

#define BIT(n) (1l << (n)) 
#define BIT_MASK(len) (BIT(len) - 1) 

int main(void) 
{ 
    struct foo f = {0}; 
    long i = 0; 

    while (f.x >= 0) { 
     f.x = BIT_MASK(++i); 
    } 
    printf("bits=%ld max=%ld\n", i, BIT_MASK(i)); 
    return 0; 
} 

Сдвиг влево до f.x отрицательно.

EDIT:

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

#include <stdio.h> 
#include <string.h> 

struct foo { 
    signed int x: 4; 
}; 

#define BIT(n) (1l << (n)) 
#define BIT_MASK(len) (BIT(len) - 1) 

int main(void) 
{ 
    long x, i = 0; 
    struct foo f; 

    f.x = -1; 
    memcpy(&x, &f, sizeof(f)); 
    while (1) { 
     if (!(x & BIT(++i))) break; 
    } 
    printf("bits=%ld max=%ld\n", i, BIT_MASK(i)); 
    return 0; 
} 

Как вы можете см. теперь он не превышает 2^(n-1) -1 (работает на long)

+2

это очень хороший ответ! Дэвид РФ, вы должны добавить некоторые комментарии и объяснения. –

+1

OP (@Richard Hansen): Проверьте этот код, работая @ [codepad] (http://codepad.org/aWKoshW3) –

+1

Спасибо Grijesh;) –

0

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

foo.x = -1; unsigned int max_size = (unsigned int) (foo.x);

половина из них будет без знака не более, половина + 1 будет подписан макс