2012-07-03 2 views
1

У меня есть код, который использует биты для хранения нескольких 1 битовых значений в char.Назначить член поля бит на char

В основном

struct BITS_8 { 
    char _1:1; 
    (...) 
    char _8:1; 
} 

Теперь я пытался передать один из этих битов в качестве параметра в функцию

void func(char bit){ 
    if(bit){ 
    // do something 
    }else{ 
    // do something else 
    } 
} 

// and the call was 
struct BITS_8 bits; 
// all bits were set to 0 before 
bits._7 = 1; 
bits._8 = 0; 
func(bits._8); 

Решение было выделить бит при вызове функции:

func(bits._8 & 0x80); 

Но я продолжал идти в //do something, потому что были установлены другие биты. Мне было интересно, правильно ли это поведение или если мой компилятор сломан. Компилятор - это встроенный компилятор, который создает код для freescale ASIC.

РЕДАКТИРОВАТЬ: 2 ошибки: передача параметра и того бита._8 должно быть 0, иначе ошибка не имеет смысла.

Разъяснение

Я заинтересован в том, что стандарт должен сказать о назначении

struct X{ 
    unsigned int k:6; 
    unsigned int y:1; 
    unsigned int z:1; 
} 

X x; 
x.k = 0; 
x.y = 1; 
x.z = 0; 

char t = X.y; 

теперь должен содержать t1 или b00000010?

+5

0x128 не один бит –

+2

'128 == 0x80', я думаю, вы этого хотели. –

+1

iirc правильно, битовое поле, определенное как char _a: 1, может принимать только значения 0 или 1, так как это 1 бит в ширину, поэтому 'func (bits._8 & 0x1);' это правильная вещь. – fvu

ответ

0

Хорошо, это была ошибка компилятора. Я написал людей, которые производят компилятор, и они подтвердили это. Это происходит только в том случае, если у вас есть бит-поле с встроенной функцией.

Их рекомендуется решение (если я не хочу ждать патча)

func((char)bits._8)); 

Другие ответы правы по поводу правильного поведения. Тем не менее я отмечаю это как ответ, поскольку это ответ на мою проблему.

0

Я не думаю, что вы можете установить 1-битный полукокса 1. Это один бит слева, чтобы определить, является ли это подпись или нет, так что вы в конечном итоге с той разницей между 0 и -1.

Что вы хотите, это unsigned char, чтобы скрыть этот бит бит. Тогда вы можете просто использовать 1s и 0s.

+0

они больше похожи на '0' и' -1', но это может быть проблема, да – unkulunkulu

+0

@unkulunkulu Упс, вы правы –

+0

Дело в том, что 'char' может быть' unsigned' стандартным и gcc например, по умолчанию используется 'unsigned char' (не знаю, зависит ли это от архитектуры). – unkulunkulu

0

На протяжении многих лет я немного подозрительно относился к этим конкретным компиляторам, нередко их интерпретация того, что можно описать, более тонкие точки стандарта C невелика. В этих случаях более прагматичный подход может помочь вам избежать безумия и выполнить работу. В этом случае это означает, что если компилятор не ведет себя рационально (что вы можете определить как поведение, совершенно отличное от того, что делает gcc), вы немного помогаете ему.

Например, вы могли бы изменить функ стать:

void func(char bit){ 
    if(bit & 1){ // mask off everything that's none of its business 
    // do something 
    }else{ 
    // do something else 
    } 
} 

И WRT вашего аддона вопроса: т должен содержать: 1. Он не может содержать 10 бинарный, так как переменное только 1 биты.

Некоторые материалы для чтения из last publicly available draft for C99

Пункт 6.7.2.1

4 битовое поле должно иметь тип, который является квалифицированным или неквалифицированным версия _Bool, подписанная INT, неподписанных Int, или некоторые другие тип реализации.

(который мне означает, что компилятор должен, по крайней мере, обрабатывать свой второй пример правильно) и

9 битовое поле интерпретируется как знаком или без знака целого типа , состоящей из указанного числа бит.107) Если значение 0 или 1 равно , которое хранится в битовом поле с ненулевой шириной типа _Bool, значение бит-поля должно сравниваться с сохраненным значением.

Как ваш компилятор предназначен для встроенного использования, где бит-поля являются довольно важной функцией, я ожидаю, что их реализация будет правильной - если они утверждают, что реализованы битовые поля.

0

Я могу понять, почему вы можете использовать char для хранения флагов, если Bool typedef'd для неподписанного int или аналогичного или если ваш компилятор не поддерживает упакованные перечисления. Вы можете настроить некоторые «флаги» с помощью макросов (я назвал их для своих значений места ниже, но имеет смысл назвать их, что они означают) Если 8 флагов недостаточно, это можно расширить до других типов до sizeof (тип) * 8 флагов.

/* if you cannot use a packed enum, you can try these macros 
* in combination with bit operations on the "flags" 
* example printf output is: 1,1,6,4,1 
* hopefully the example doesn't make it more confusing 
* if so see fvu's example */ 

#include <stdio.h> /* for printf */ 
#define ONE ((char) 1) 
#define TWO (((char) 1)<<1) 
#define FOUR (((char) 1)<<2) 
#define EIGHT (((char) 1)<<3) 
#define SIXTEEN (((char) 1)<<4) 
#define THIRTYTWO (((char) 1)<<5) 
#define SIXTYFOUR (((char) 1)<<6) 
#define ONETWENTYEIGHT (((char) 1)<<7) 

int main(void){ 
printf("%d,%d,%d,%d,%d\n",ONE & ONE, ONE | ONE, TWO | 6, FOUR & 6, sizeof(ONE)); 
} 
Смежные вопросы