2013-05-22 4 views
-1

Я хочу определить булевский макрос в C, который использует менее 4 байт. Я рассмотрел это, и, возможно, можно определить макрос asm с gcc, который может быть меньше. Важно, чтобы определение было небольшим, потому что у меня будет десятки тысяч матриц, которые содержат эти логические значения, и важно, чтобы они были максимально эффективными по мере возможности памяти. В идеале я хочу определить 4-битный или 8-битный макрос, который представляет true и false, и будет оцениваться как таковой в if-statement.Определение минимально возможного размера макроса в C

Edit:

Когда я определяю макрос

#define True 0 
#define False !True 

, а затем распечатать размер, он возвращает размер 4 байта, что очень неэффективно.

Edit2:

Я только что прочитал на bitpacking, и тем не менее маленькие кусочки я мог бы иметь для булева будет лучше. Я просто не слишком уверен, как бить рюкзак, который имеет размер в несколько бит.

Edit3:

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

#define false (unsigned char(0)) 
#define true (!false) 

int main() { 
    if (true) { 
     printf("The size of true is %d\n", sizeof(true)); 
    } 
} 

дает следующий вывод

test.c: In function ‘main’: 
test.c:8:9: error: expected ‘)’ before numeric constant 
test.c:9:51: error: expected ‘)’ before numeric constant 
+12

Как вы определяете размер макроса? –

+0

Вы ищете 'char' (или' int8_t')? – mpartel

+0

Вы можете быть смущены - макрос не является переменной или типом данных (это что-то обрабатывается и расширяется компилятором/препроцессором.) Наименьшее представление логического значения немного, поэтому, возможно, вам нужны сжатые данные структурная упаковка 8 булевых в один байт. Пожалуйста, отредактируйте свой вопрос, если да, или объясните, почему это должно быть 4 или 8 бит. –

ответ

4

Попробуйте это вместо того, чтобы для ваших макросов:

#define false ((unsigned char) 0) 
#define true (!false) 

Это не исправит ваше пространство нуждается хотя. Для более эффективного хранения вам необходимо использовать биты:

void SetBoolValue(int bitOffset, unsigned char *array, bool value) 
{ 
    int index = bitOffset >> 3; 
    int mask = 1 << (bitOffset & 0x07); 

    if (value) 
     array[index] |= mask; 
    else 
     array[index] &= ~mask; 
} 

bool GetBoolValue(int bitOffset, unsigned char *array) 
{ 
    int index = bitOffset >> 3; 
    int mask = 1 << (bitOffset & 0x07); 

    return array[index] & mask; 
} 

Где каждое значение «массива» может содержать 8 точек. В современных системах может быть быстрее использовать U32 или U64 в качестве массива, но он может занимать больше места для меньших объемов данных.

Для упаковки больших объемов данных:

void SetMultipleBoolValues(int bitOffset, unsigned char *array, int value, int numBitsInValue) 
{ 
    for(int i=0; i<numBitsInValue; i++) 
    { 
     SetBoolValue(bitOffset + i, array, (value & (1 << i))); 
    } 
} 

А вот бы водитель:

int main(void) 
{ 
    static char array[32]; // Static so it starts 0'd. 
    int value = 1234; // An 11-bit value to pack 

    for(int i=0; i<4; i++) 
     SetMultipleBoolValues(i * 11, array, value, 11); // 11 = 11-bits of data - do it 4 times 

    for(int i=0; i<32; i++) 
     printf("%c", array[i]); 

    return 0; 
} 
+0

Я пробовал это; но он не оценивается как истинный, если у меня есть оператор if, если (True) {/ * Do Something * /} – user1876508

+0

Поскольку мой макрос был обратным - хромым на меня. Исправлена. –

+0

Обратите внимание, что это должно быть '#define true (! False)' – jxh

0

Вы должны, вероятно, просто использовать unsigned char, это будет наименьшим индивидуально адресуемые тип:

typedef unsigned char smallBool; 

smallBool boolMatrix[M][N]; 

выше будет использовать M * N байт для матрицы.

Конечно, расточительно CHAR_BIT - 1 бит для хранения одного бита ... расточительный. Рассмотрим бит-упаковку булевых значений.

+0

Как бы они оценивались в выражении if? Например, скажем, я хочу посмотреть на i-ю строку и j-й столбец и сказать if (boolMatrix [i] [j]) {return 1} – user1876508

1

Если вы используете это в структуре, то вам нужно будет использовать битовое поле ,

struct { 
    unsigned flag : 1; 
    /* other fields */ 
}; 

Если Вы желаете массив логических значений, вы должны реализовать вектор битов (я собирался реализовать один, но Майкл Dorgan уже сделали это).

1

Прежде всего, не существует хранилища, связанного с вашими макросами; они расширяются до целого числа константы0 и 1. Значение sizeof оценивается как 4, поскольку выражения имеют целочисленный тип. Вы можете назначить эти значения объектам меньшего типа (short или char).

Для меня, жизнь стала намного проще, когда я остановился с помощью TRUE и FALSE макросы . Помните, что в C целочисленное выражение с нулевой оценкой вычисляется как ложное, а все ненулевые значения интегральных выражений оцениваются как истинные.

Если вы хотите сохранить значения в чем-то меньшим, чем 8 бит, то вы будете иметь, чтобы сделать свою собственную битовую упаковку, что-то вроде

#define TEST(x,bit) ((x) & (1 << (bit))) 
#define SET(x,bit) ((x) |= (1 << (bit))) 
#define CLEAR(x,bit) ((x) &= ~(1 << (bit))) 

Самого маленький полезный типа для этого является unsigned char. Поэтому, если вам нужно хранить N однобитовых значений, вам нужен массив из N/CHAR_BIT + 1 элементов. Например, чтобы сохранить 10 однобитовых логических значений, вам нужно два восьмибитных элемента массива. Биты с 0 по 7 будут храниться в элементе 0, а биты с 8 по 10 будут храниться в элементе 1.

Так, что-то вроде

#define MAX_BITS 24 
unsigned char bits[MAX_BITS/CHAR_BIT + 1]; 

int bit = ...; 

SET(bits[bit/CHAR_BIT], bit % CHAR_BIT); 

if (TEST(bits[bit/CHAR_BIT], bit % CHAR_BIT)) 
{ 
    // do something if bit is set 
} 

CLEAR(bits[bit/CHAR_BIT], bit % CHAR_BIT); 

Никаких гарантий не явные или подразумеваемые; Я не очень много кручу. Но, надеюсь, это, по крайней мере, указывает вам в правильном направлении.


1. Случай провоцирующий был кто-то сбросив заголовок где TRUE == FALSE. Не самый продуктивный день.

Смежные вопросы